動態

詳情 返回 返回

div + transform 實現旋轉圖片並得到期望的佔位盒子 - 動態 詳情

效果圖

20250912_135633.gif

使用示例

<script setup lang="ts">
import RotatedImage from "**/RotatedImage.vue";
import { ref } from "vue";

const value = ref(50);
const clockwise = ref(true);
const src = ref(
  "https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg"
);
</script>

<template>
  <section>
    <n-radio-group v-model:value="clockwise" name="radiogroup">
      <n-space>
        <n-radio :value="true"> 順時針 </n-radio>
        <n-radio :value="false"> 逆時針 </n-radio>
      </n-space>
    </n-radio-group>
    <n-radio-group v-model:value="src" name="radiogroup">
      <n-space>
        <n-radio
          value="https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg"
        >
          圖1
        </n-radio>
        <n-radio
          value="https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg"
        >
          圖2
        </n-radio>
      </n-space>
    </n-radio-group>
    <n-slider v-model:value="value" />
    <RotatedImage :clockwise="clockwise" :width="value + '%'" :src="src" />
    ewrwrwrwrwrwrwrwrwrwrwrwrwrwrwrer割讓給rr割讓給weeeeeeeeeeeue隔熱隔熱eeeeeeregregious
  </section>
</template>

<style scoped lang="scss">
section {
  margin: 50px;
  width: 600px;
  height: 800px;
  border: 1px solid;
  font-size: 51px;
  word-wrap: break-word;
  .rotated-image {
    float: left;
    clear: both;
  }
}
</style>

RotatedImage.vue

<script setup lang="ts">
import { onUnmounted, ref, watch } from "vue";

interface Props {
  src: string;
  /** 旋轉後圖片的寬度 */
  width?: number | string;
  /** 旋轉後圖片的高度 */
  height?: number | string;
  /** 順時針旋轉 */
  clockwise?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
  clockwise: true,
});

const divRef = ref<HTMLDivElement>();
let img: HTMLImageElement;

function setDivDimensions(width?: string | number, height?: string | number) {
  const div = divRef.value!;
  if (width) {
    if (typeof width === "number") div.style.width = `${width}px`;
    else div.style.width = width;
  }
  if (height) {
    if (typeof height === "number") div.style.height = `${height}px`;
    else div.style.height = height;
  }
}

watch(
  () => props,
  ({ width, height }) => {
    requestAnimationFrame(() => {
      setDivDimensions(width, height);
      rect();
    });
  },
  { immediate: true, deep: true }
);

function rect() {
  const div = divRef.value!;
  if (!img || !div) return;

  const { naturalWidth, naturalHeight } = img;
  const aspectRatio = naturalWidth / naturalHeight;

  let width, height;
  if (props.width || props.height) {
    const rect = div.getBoundingClientRect();
    const targetWidth = rect.width;
    const targetHeight = rect.height;
    if (props.width && props.height) {
      width = targetWidth;
      height = targetHeight;
    } else if (props.width) {
      width = targetWidth;
      height = targetWidth * aspectRatio;
    } else if (props.height) {
      width = targetHeight / aspectRatio;
      height = targetHeight;
    }
  } else {
    width = naturalHeight;
    height = naturalWidth;
  }

  setDivDimensions(props.width || width, props.height || height);

  img.style.width = height + "px";
  img.style.height = width + "px";

  rotated();
}
function rotated() {
  const { width, height } = divRef.value!.getBoundingClientRect();

  img.style.width = height + "px";
  img.style.height = width + "px";

  if (props.clockwise) {
    img.style.transformOrigin = "left top";
    img.style.transform = `translate(${width}px, 0px) rotate(90deg)`;
  } else {
    img.style.transformOrigin = "right top";
    img.style.transform = `translate(${-height}px, 0px) rotate(-90deg)`;
  }
}
function load(event: Event) {
  if (event.target instanceof HTMLImageElement) {
    img = event.target;
    rect();
  }
}

const observe = new ResizeObserver(rect);
requestAnimationFrame(() => observe.observe(divRef.value!));
onUnmounted(() => {
  observe.disconnect();
});
</script>

<template>
  <div ref="divRef" class="rotated-image">
    <img :src="src" @load="load" />
  </div>
</template>

<style scoped lang="scss">
.rotated-image {
  display: inline-block;
}
</style>
user avatar dingtongya 頭像 cyzf 頭像 jingdongkeji 頭像 yelloxing 頭像 zourongle 頭像 6fafa 頭像 dawanzi_6278b06ec111c 頭像 leexiaohui1997 頭像 anchen_5c17815319fb5 頭像 banana_god 頭像 u_17443142 頭像 talkcss 頭像
點贊 123 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.