Skip to content

Vue实现截图遮罩效果 #64

@varHarrie

Description

@varHarrie
<template>
  <button @click="onScreenshot">Screenshot</button>
  <div v-if="cropping" class="cropper"
    :style="style"
    @mousedown="onStart"
    @mousemove="onMove"
    @mouseup="onEnd"
  >
    <div class="mask" v-if="style"></div>
    <div class="area" v-if="style"></div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'

const cropping = ref(false);
const startPoint = ref();
const endPoint = ref();

const rect = computed(() => {
  if (!startPoint.value || !endPoint.value) return null;

   return {
    x: Math.min(startPoint.value.x, endPoint.value.x),
    y: Math.min(startPoint.value.y, endPoint.value.y),
    width: Math.abs(endPoint.value.x - startPoint.value.x),
    height: Math.abs(endPoint.value.y - startPoint.value.y),
  };
})

const style = computed(() => {
  if (!rect.value) return null

  return {
    '--x': `${rect.value.x}px`,
    '--y': `${rect.value.y}px`,
    '--width': `${rect.value.width}px`,
    '--height': `${rect.value.height}px`,
  };
});

const onScreenshot = () => {
  cropping.value = true;
}

const onStart = (e) => {
  startPoint.value = { x: e.clientX, y: e.clientY };
};

const onMove = (e) => {
  if (!startPoint.value) return;
  endPoint.value = { x: e.clientX, y: e.clientY };
};

const onEnd = () => {
  console.log(rect.value);
  startPoint.value = undefined;
  endPoint.value = undefined;
  cropping.value = false;
};
</script>

<style>
.cropper {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  cursor: crosshair;
}

.mask {
  width: 100%;
  height: 100%;
  background: rgba(0,0,0,0.2);
  clip-path: polygon(
    0% 0%,
    0% 100%,
    var(--x) 100%,
    var(--x) var(--y),
    calc(var(--x) + var(--width)) var(--y),
    calc(var(--x) + var(--width)) calc(var(--y) + var(--height)),
    var(--x) calc(var(--y) + var(--height)),
    var(--x) 100%,
    100% 100%,
    100% 0%
  );
}

.area {
  position: absolute;
  top: var(--y);
  left: var(--x);
  width: var(--width);
  height: var(--height);
  border: 1px solid black;
}
</style>

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions