截图功能
需要实现的功能总结
总结需要实现的需求,同时确定对应组件需要
方法
- 图片渲染:
.render()
- 放大缩小回正:
.zoomIn()、.zoomOut()、.zoomInit()
- 清空画布:
.clean()
- 导出图片:
.preview(type?:'base64)'|'blob'):'base64)'|'blob'
- 下载图片:
.download(filename:string, ext?:'png'|'jpeg'|'webp') 自动触发浏览器下载功能
事件
- 被拖拽:
onResize({x,y,w,h})
- 被移动:
onDrag({x,y})
选项
- 图片
- 能否拖动
- 截图框
- 截图框能否拖动
- 截图框固定大小
- 截图框是否限制在图片内
- 打开图片的行为:大图是否铺满,小图是否铺满
- 是否锁定比例
- x比例
- y比例
- 提供常用比例选择
- 默认
- 默认预览返回的图片格式
- 默认下载的图片格式
temp
// var target = event.target;
// let x = parseFloat(target.getAttribute("data-x")) || 0;
// let y = parseFloat(target.getAttribute("data-y")) || 0;
// // update the element's style
// target.style.width = event.rect.width + "px";
// target.style.height = event.rect.height + "px";
// // translate when resizing from top or left edges
// x += event.deltaRect.left;
// y += event.deltaRect.top;
// target.style.transform = "translate(" + x + "px," + y + "px)";
// target.setAttribute("data-x", x);
// target.setAttribute("data-y", y);
// let target = event.target;
// // keep the dragged position in the data-x/data-y attributes
// let x = (parseFloat(target.getAttribute("data-x")) || 0) + event.dx;
// let y = (parseFloat(target.getAttribute("data-y")) || 0) + event.dy;
// // translate the element
// target.style.transform = "translate(" + x + "px, " + y + "px)";
// // update the posiion attributes
// target.setAttribute("data-x", x);
// target.setAttribute("data-y", y);
<!--
* @Author: CPS
* @email: 373704015@qq.com
* @Date: 2022-11-30 16:03:56.099670
* @Last Modified by: CPS
* @Last Modified time: 2022-11-30 16:03:56.099670
* @Filename main.py
* @Description: 基于interact插件创建的一个拖拽缩放对象
-->
<template>
<!-- 拖拽框本体 -->
<div
:id="props.id"
:style="{
width: width + 'px',
height: height + 'px',
transform: transform,
}"
:class="[
'text-gray-600',
'text-center align-middle',
'cps__dragResizeContainer',
'absolute w-20 h-20 z-50',
'border-2 border-solid border-sky-500 touch-none text-white font-sans',
props.class,
]"
>
<div
v-show="props.showInfo"
:class="[
'absolute min-w-[300px] w-full h-full left-1/2 -translate-x-[50%] translate-y-[100%] box-border p-2 align-middle',
]"
>
<strong class="box-border w-full block bg-red-200/75">裁剪范围: {{ currtW }} x {{ currtH }}</strong>
<strong class="box-border w-full block bg-red-200/75"
>真实尺寸: {{ localStore.crop.endX }} x {{ localStore.crop.endY }}</strong
>
<strong class="box-border w-full block bg-red-200/75">缩放比例: {{ localStore.imgScale }}</strong>
</div>
</div>
</template>
<script setup lang="ts">
import interact from "interactjs";
import localStore from "@/components/ImageCuter/store";
import type { Ref } from "vue";
const currtW = ref(0);
const currtH = ref(0);
export interface Coords {
width: Ref<number> | number;
height: Ref<number> | number;
top: Ref<number> | number;
left: Ref<number> | number;
}
const emit = defineEmits<{
(e: "update:width", coordValue: number): void;
(e: "update:height", coordValue: number): void;
(e: "update:top", coordValue: number): void;
(e: "update:left", coordValue: number): void;
(e: "onResize", event: Event, coords: Coords): void;
(e: "onDrag", event: Event, coords: Coords): void;
}>();
const props = withDefaults(
defineProps<{
id: string; // 唯一ID
class?: string; // 自定义样式
width: number; // 以下四个属性提供一个响应式对象 ref/reactive 用来绑定对应属性
height: number;
top: number;
left: number;
showInfo?: boolean;
}>(),
{
id: "",
class: "",
showInfo: false,
}
);
const transform = computed(() => `translate(${props.left}px, ${props.top}px`);
function init(id: string): void {
const element = document.getElementById(props.id);
if (!element) return;
const main = interact(element)
.resizable({
// resize from all edges and corners
edges: { left: true, right: true, bottom: true, top: true },
modifiers: [
interact.modifiers.restrictEdges({ outer: "parent" }),
interact.modifiers.restrictSize({ min: { width: 1, height: 1 } }),
],
listeners: {
move(event) {
const top = props.top + Math.trunc(event.deltaRect.top);
const left = props.left + Math.trunc(event.deltaRect.left);
const width = event.rect.width;
const height = event.rect.height;
currtW.value = Math.trunc(width);
currtH.value = Math.trunc(height);
emit("update:top", top);
emit("update:left", left);
emit("update:width", width);
emit("update:height", height);
emit("onResize", event, { width, height, top, left });
},
},
})
.draggable({
listeners: {
move(event) {
const top = props.top + Math.trunc(event.dy);
const left = props.left + Math.trunc(event.dx);
const width = event.rect.width;
const height = event.rect.height;
currtW.value = Math.trunc(width);
currtH.value = Math.trunc(height);
emit("update:top", top);
emit("update:left", left);
emit("onDrag", event, { width, height, top, left });
},
},
inertia: true,
modifiers: [
interact.modifiers.restrictRect({
restriction: "parent",
endOnly: true,
}),
],
})
.on("up", (e) => {
const target = e.target;
});
}
onMounted(() => init(props.id));
</script>