v3-comf-dm 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +175 -0
- package/dist/components/ImageCropper/index.vue.d.ts +67 -0
- package/dist/components/ImageCropper/types.d.ts +33 -0
- package/dist/components/ScaleContainer/index.vue.d.ts +48 -0
- package/dist/components/ScaleContainer/types.d.ts +8 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.esm.js +718 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/install.d.ts +7 -0
- package/dist/style.css +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/package.json +68 -0
- package/packages/components/ImageCropper/index.vue +826 -0
- package/packages/components/ImageCropper/types.ts +47 -0
- package/packages/components/ScaleContainer/index.vue +129 -0
- package/packages/components/ScaleContainer/types.ts +10 -0
- package/packages/components/index.ts +9 -0
- package/packages/index.ts +26 -0
- package/packages/install.ts +21 -0
- package/packages/styles/index.scss +8 -0
- package/packages/types/index.ts +3 -0
- package/packages/utils/index.ts +56 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../packages/components/ScaleContainer/index.vue","../packages/components/ImageCropper/index.vue","../packages/install.ts","../packages/utils/index.ts","../packages/index.ts"],"sourcesContent":["<template>\r\n <div ref=\"scaleContainer\" class=\"vc-scale-container\" :style=\"containerStyle\">\r\n <div class=\"vc-scale-wrapper\" :style=\"wrapperStyle\">\r\n <slot></slot>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onMounted, onBeforeUnmount, nextTick } from 'vue'\r\nimport type { ScaleContainerProps } from './types'\r\n\r\nconst props = withDefaults(defineProps<ScaleContainerProps>(), {\r\n designWidth: 1920,\r\n designHeight: 1080,\r\n keepAspectRatio: true,\r\n scaleMode: 'fit',\r\n detectBrowserZoom: true,\r\n})\r\n\r\nconst scaleContainer = ref<HTMLElement | null>(null)\r\nconst scale = ref(1)\r\nconst scaleX = ref(1)\r\nconst scaleY = ref(1)\r\nconst containerWidth = ref(1920)\r\nconst containerHeight = ref(1080)\r\n\r\n// 容器样式\r\nconst containerStyle = computed(() => ({\r\n width: `${containerWidth.value}px`,\r\n height: `${containerHeight.value}px`,\r\n position: 'relative' as const,\r\n overflow: 'hidden' as const,\r\n}))\r\n\r\n// 包装器样式\r\nconst wrapperStyle = computed(() => {\r\n const commonStyle = {\r\n width: `${props.designWidth}px`,\r\n height: `${props.designHeight}px`,\r\n transformOrigin: 'top left' as const,\r\n }\r\n\r\n if (props.keepAspectRatio && (props.scaleMode === 'fit' || props.scaleMode === 'fill')) {\r\n const sw = props.designWidth * scale.value\r\n const sh = props.designHeight * scale.value\r\n return {\r\n ...commonStyle,\r\n transform: `scale(${scale.value})`,\r\n position: 'absolute' as const,\r\n top: '50%',\r\n left: '50%',\r\n marginTop: `-${sh / 2}px`,\r\n marginLeft: `-${sw / 2}px`,\r\n }\r\n }\r\n\r\n return {\r\n ...commonStyle,\r\n transform: `scale(${scaleX.value}, ${scaleY.value})`,\r\n }\r\n})\r\n\r\nconst updateScale = () => {\r\n const el = scaleContainer.value\r\n if (!el || !el.parentElement) return\r\n\r\n const parent = el.parentElement\r\n let pw = parent.clientWidth || window.innerWidth\r\n let ph = parent.clientHeight || window.innerHeight\r\n\r\n if (pw === 0) pw = window.innerWidth\r\n if (ph === 0) ph = window.innerHeight\r\n\r\n containerWidth.value = pw\r\n containerHeight.value = ph\r\n\r\n const sx = pw / props.designWidth\r\n const sy = ph / props.designHeight\r\n\r\n if (props.scaleMode === 'stretch') {\r\n scaleX.value = sx\r\n scaleY.value = sy\r\n } else if (props.keepAspectRatio) {\r\n scale.value = props.scaleMode === 'fit' ? Math.min(sx, sy) : Math.max(sx, sy)\r\n } else {\r\n scaleX.value = sx\r\n scaleY.value = sy\r\n }\r\n}\r\n\r\nlet resizeObserver: ResizeObserver | null = null\r\nconst handleResize = () => updateScale()\r\n\r\nonMounted(() => {\r\n nextTick(() => {\r\n updateScale()\r\n window.addEventListener('resize', handleResize)\r\n\r\n if (window.ResizeObserver && scaleContainer.value?.parentElement) {\r\n resizeObserver = new ResizeObserver(handleResize)\r\n resizeObserver.observe(scaleContainer.value.parentElement)\r\n }\r\n })\r\n})\r\n\r\nonBeforeUnmount(() => {\r\n window.removeEventListener('resize', handleResize)\r\n if (resizeObserver) {\r\n resizeObserver.disconnect()\r\n }\r\n})\r\n\r\ndefineOptions({\r\n name: 'VcScaleContainer'\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.vc-scale-container {\r\n margin: 0;\r\n padding: 0;\r\n display: block;\r\n}\r\n.vc-scale-wrapper {\r\n box-sizing: border-box;\r\n display: block;\r\n}\r\n</style>\r\n","<template>\r\n <div ref=\"containerRef\" class=\"vc-image-cropper\" :style=\"containerStyle\" tabindex=\"0\">\r\n <div v-if=\"!imageSrc\" class=\"vc-image-cropper-placeholder\">\r\n <div class=\"placeholder-content\">\r\n <svg\r\n width=\"64\"\r\n height=\"64\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n >\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"></rect>\r\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"></circle>\r\n <polyline points=\"21 15 16 10 5 21\"></polyline>\r\n </svg>\r\n <p>请选择图片</p>\r\n </div>\r\n </div>\r\n\r\n <div v-else class=\"vc-image-cropper-content\" ref=\"contentRef\">\r\n <div\r\n ref=\"imageWrapperRef\"\r\n class=\"vc-image-wrapper\"\r\n :style=\"imageWrapperStyle\"\r\n @mousedown=\"handleMouseDown\"\r\n @wheel.prevent=\"handleWheel\"\r\n >\r\n <img\r\n ref=\"imageRef\"\r\n :src=\"imageSrc\"\r\n :style=\"imageStyle\"\r\n @load=\"handleImageLoad\"\r\n draggable=\"false\"\r\n />\r\n\r\n <!-- 裁剪框 -->\r\n <div\r\n v-if=\"imageLoaded\"\r\n ref=\"cropBoxRef\"\r\n class=\"vc-crop-box\"\r\n :style=\"cropBoxStyle\"\r\n @mousedown.stop=\"handleCropBoxMouseDown\"\r\n >\r\n <!-- 网格线 -->\r\n <div v-if=\"showGrid\" class=\"vc-crop-grid\">\r\n <div class=\"grid-line grid-line-h1\"></div>\r\n <div class=\"grid-line grid-line-h2\"></div>\r\n <div class=\"grid-line grid-line-v1\"></div>\r\n <div class=\"grid-line grid-line-v2\"></div>\r\n </div>\r\n\r\n <!-- 控制点 -->\r\n <div\r\n v-for=\"(handle, index) in cropHandles\"\r\n :key=\"index\"\r\n class=\"vc-crop-handle\"\r\n :class=\"handle.class\"\r\n :style=\"handle.style\"\r\n @mousedown.stop=\"handleResizeStart($event, handle.type)\"\r\n ></div>\r\n </div>\r\n </div>\r\n\r\n <!-- 工具栏 -->\r\n <div v-if=\"imageLoaded\" class=\"vc-cropper-toolbar\">\r\n <div v-if=\"zoomable\" class=\"toolbar-group\">\r\n <label class=\"toolbar-label\">缩放:</label>\r\n <input\r\n v-model.number=\"zoom\"\r\n type=\"range\"\r\n :min=\"minZoom\"\r\n :max=\"maxZoom\"\r\n :step=\"0.1\"\r\n class=\"toolbar-slider\"\r\n @input=\"handleZoomChange\"\r\n />\r\n <span class=\"toolbar-value\">{{ Math.round(zoom * 100) }}%</span>\r\n </div>\r\n\r\n <div v-if=\"rotatable\" class=\"toolbar-group\">\r\n <button class=\"toolbar-btn\" @click=\"rotateImage(-90)\" title=\"逆时针旋转\">↺</button>\r\n <button class=\"toolbar-btn\" @click=\"rotateImage(90)\" title=\"顺时针旋转\">↻</button>\r\n </div>\r\n\r\n <div class=\"toolbar-group\">\r\n <button class=\"toolbar-btn toolbar-btn-primary\" @click=\"handleCrop\">确认裁剪</button>\r\n <button class=\"toolbar-btn\" @click=\"handleCancel\">取消</button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'\r\nimport type { ImageCropperProps, ImageCropperEmits, CropArea } from './types'\r\n\r\nconst props = withDefaults(defineProps<ImageCropperProps>(), {\r\n cropMode: 'free',\r\n minWidth: 50,\r\n minHeight: 50,\r\n showGrid: true,\r\n rotatable: true,\r\n zoomable: true,\r\n initialZoom: 1,\r\n containerWidth: '100%',\r\n containerHeight: '600px',\r\n})\r\n\r\nconst emit = defineEmits<ImageCropperEmits>()\r\n\r\n// Refs\r\nconst containerRef = ref<HTMLElement | null>(null)\r\nconst contentRef = ref<HTMLElement | null>(null)\r\nconst imageWrapperRef = ref<HTMLElement | null>(null)\r\nconst imageRef = ref<HTMLImageElement | null>(null)\r\nconst cropBoxRef = ref<HTMLElement | null>(null)\r\n\r\n// 状态\r\nconst imageLoaded = ref(false)\r\nconst imageNaturalWidth = ref(0)\r\nconst imageNaturalHeight = ref(0)\r\nconst imageDisplayWidth = ref(0)\r\nconst imageDisplayHeight = ref(0)\r\nconst rotation = ref(0)\r\nconst zoom = ref(props.initialZoom)\r\nconst minZoom = ref(0.1)\r\nconst maxZoom = ref(5)\r\n\r\n// 裁剪区域(相对于图片的坐标)\r\nconst cropArea = ref<CropArea>({\r\n x: 0,\r\n y: 0,\r\n width: 0,\r\n height: 0,\r\n})\r\n\r\n// 拖拽状态\r\nconst isDragging = ref(false)\r\nconst isResizing = ref(false)\r\nconst dragType = ref<string>('')\r\nconst dragStart = ref({ x: 0, y: 0 })\r\nconst cropStart = ref<CropArea>({ x: 0, y: 0, width: 0, height: 0 })\r\n\r\n// 容器样式\r\nconst containerStyle = computed(() => ({\r\n width:\r\n typeof props.containerWidth === 'number' ? `${props.containerWidth}px` : props.containerWidth,\r\n height:\r\n typeof props.containerHeight === 'number'\r\n ? `${props.containerHeight}px`\r\n : props.containerHeight,\r\n}))\r\n\r\n// 图片包装器样式\r\nconst imageWrapperStyle = computed(() => ({\r\n transform: `rotate(${rotation.value}deg) scale(${zoom.value})`,\r\n transformOrigin: 'center center',\r\n}))\r\n\r\n// 图片样式\r\nconst imageStyle = computed(() => ({\r\n width: `${imageDisplayWidth.value}px`,\r\n height: `${imageDisplayHeight.value}px`,\r\n display: 'block',\r\n}))\r\n\r\n// 裁剪框样式\r\nconst cropBoxStyle = computed(() => ({\r\n left: `${cropArea.value.x}px`,\r\n top: `${cropArea.value.y}px`,\r\n width: `${cropArea.value.width}px`,\r\n height: `${cropArea.value.height}px`,\r\n}))\r\n\r\n// 裁剪控制点\r\nconst cropHandles = computed(() => {\r\n return [\r\n { type: 'nw', class: 'handle-nw', style: { top: '-4px', left: '-4px', cursor: 'nwse-resize' } },\r\n {\r\n type: 'ne',\r\n class: 'handle-ne',\r\n style: { top: '-4px', right: '-4px', cursor: 'nesw-resize' },\r\n },\r\n {\r\n type: 'sw',\r\n class: 'handle-sw',\r\n style: { bottom: '-4px', left: '-4px', cursor: 'nesw-resize' },\r\n },\r\n {\r\n type: 'se',\r\n class: 'handle-se',\r\n style: { bottom: '-4px', right: '-4px', cursor: 'nwse-resize' },\r\n },\r\n {\r\n type: 'n',\r\n class: 'handle-n',\r\n style: { top: '-4px', left: '50%', transform: 'translateX(-50%)', cursor: 'ns-resize' },\r\n },\r\n {\r\n type: 's',\r\n class: 'handle-s',\r\n style: { bottom: '-4px', left: '50%', transform: 'translateX(-50%)', cursor: 'ns-resize' },\r\n },\r\n {\r\n type: 'w',\r\n class: 'handle-w',\r\n style: { top: '50%', left: '-4px', transform: 'translateY(-50%)', cursor: 'ew-resize' },\r\n },\r\n {\r\n type: 'e',\r\n class: 'handle-e',\r\n style: { top: '50%', right: '-4px', transform: 'translateY(-50%)', cursor: 'ew-resize' },\r\n },\r\n ]\r\n})\r\n\r\n// 图片加载完成\r\nconst handleImageLoad = () => {\r\n if (!imageRef.value) return\r\n\r\n imageNaturalWidth.value = imageRef.value.naturalWidth\r\n imageNaturalHeight.value = imageRef.value.naturalHeight\r\n\r\n nextTick(() => {\r\n updateImageDisplaySize()\r\n initCropArea()\r\n imageLoaded.value = true\r\n emit('ready')\r\n })\r\n}\r\n\r\n// 更新图片显示尺寸\r\nconst updateImageDisplaySize = () => {\r\n if (!contentRef.value || !imageRef.value) return\r\n\r\n // 使用内容区域的尺寸作为参考\r\n const containerWidth = contentRef.value.clientWidth\r\n const containerHeight = contentRef.value.clientHeight\r\n\r\n if (containerWidth === 0 || containerHeight === 0) return\r\n\r\n const naturalAspect = imageNaturalWidth.value / imageNaturalHeight.value\r\n const containerAspect = containerWidth / containerHeight\r\n\r\n if (naturalAspect > containerAspect) {\r\n // 图片较宽,以容器宽度为准\r\n imageDisplayWidth.value = containerWidth * 0.9\r\n imageDisplayHeight.value = (containerWidth * 0.9) / naturalAspect\r\n } else {\r\n // 图片较高,以容器高度为准\r\n imageDisplayHeight.value = containerHeight * 0.9\r\n imageDisplayWidth.value = containerHeight * 0.9 * naturalAspect\r\n }\r\n}\r\n\r\n// 初始化裁剪区域\r\nconst initCropArea = () => {\r\n const width = imageDisplayWidth.value\r\n const height = imageDisplayHeight.value\r\n const size = Math.min(width, height) * 0.8\r\n\r\n let cropWidth = size\r\n let cropHeight = size\r\n\r\n if (props.cropMode === 'fixed') {\r\n cropWidth = props.fixedWidth || size\r\n cropHeight = props.fixedHeight || size\r\n } else if (props.cropMode === 'ratio' && props.aspectRatio) {\r\n if (width / height > props.aspectRatio) {\r\n cropHeight = size\r\n cropWidth = size * props.aspectRatio\r\n } else {\r\n cropWidth = size\r\n cropHeight = size / props.aspectRatio\r\n }\r\n }\r\n\r\n cropArea.value = {\r\n x: (width - cropWidth) / 2,\r\n y: (height - cropHeight) / 2,\r\n width: cropWidth,\r\n height: cropHeight,\r\n }\r\n}\r\n\r\n// 鼠标按下(拖拽图片)\r\nconst handleMouseDown = (e: MouseEvent) => {\r\n if (e.target !== imageWrapperRef.value) return\r\n isDragging.value = true\r\n dragStart.value = { x: e.clientX, y: e.clientY }\r\n document.addEventListener('mousemove', handleMouseMove)\r\n document.addEventListener('mouseup', handleMouseUp)\r\n e.preventDefault()\r\n}\r\n\r\n// 裁剪框鼠标按下\r\nconst handleCropBoxMouseDown = (e: MouseEvent) => {\r\n if (e.target === cropBoxRef.value) {\r\n isDragging.value = true\r\n dragType.value = 'crop-box'\r\n dragStart.value = { x: e.clientX, y: e.clientY }\r\n cropStart.value = { ...cropArea.value }\r\n document.addEventListener('mousemove', handleMouseMove)\r\n document.addEventListener('mouseup', handleMouseUp)\r\n e.preventDefault()\r\n }\r\n}\r\n\r\n// 开始调整大小\r\nconst handleResizeStart = (e: MouseEvent, type: string) => {\r\n isResizing.value = true\r\n dragType.value = type\r\n dragStart.value = { x: e.clientX, y: e.clientY }\r\n cropStart.value = { ...cropArea.value }\r\n document.addEventListener('mousemove', handleMouseMove)\r\n document.addEventListener('mouseup', handleMouseUp)\r\n e.preventDefault()\r\n}\r\n\r\n// 鼠标移动\r\nconst handleMouseMove = (e: MouseEvent) => {\r\n if (!contentRef.value) return\r\n\r\n // 计算鼠标在屏幕上的移动距离,并除以缩放倍数\r\n const screenDeltaX = (e.clientX - dragStart.value.x) / zoom.value\r\n const screenDeltaY = (e.clientY - dragStart.value.y) / zoom.value\r\n\r\n // 【核心修复】将屏幕移动坐标转换回旋转后的本地坐标系\r\n // 公式:x' = x*cos(θ) + y*sin(θ), y' = -x*sin(θ) + y*cos(θ)\r\n // 这里 θ 取负值,因为我们要从屏幕坐标转回组件本地坐标\r\n const rad = (-rotation.value * Math.PI) / 180\r\n const cos = Math.cos(rad)\r\n const sin = Math.sin(rad)\r\n\r\n const deltaX = screenDeltaX * cos - screenDeltaY * sin\r\n const deltaY = screenDeltaX * sin + screenDeltaY * cos\r\n\r\n if (isDragging.value && dragType.value === 'crop-box') {\r\n // 拖拽裁剪框\r\n // 【核心修复】由于裁剪框在旋转容器内部,边界限制应始终使用图片的原始显示尺寸\r\n const width = imageDisplayWidth.value\r\n const height = imageDisplayHeight.value\r\n const newX = Math.max(0, Math.min(cropStart.value.x + deltaX, width - cropArea.value.width))\r\n const newY = Math.max(0, Math.min(cropStart.value.y + deltaY, height - cropArea.value.height))\r\n\r\n cropArea.value.x = newX\r\n cropArea.value.y = newY\r\n } else if (isResizing.value) {\r\n // 调整裁剪框大小\r\n resizeCropBox(deltaX, deltaY)\r\n }\r\n}\r\n\r\n// 调整裁剪框大小\r\nconst resizeCropBox = (deltaX: number, deltaY: number) => {\r\n const width = imageDisplayWidth.value\r\n const height = imageDisplayHeight.value\r\n const { x, y, width: w, height: h } = cropStart.value\r\n const type = dragType.value\r\n\r\n let newX = x\r\n let newY = y\r\n let newWidth = w\r\n let newHeight = h\r\n\r\n // 根据拖拽类型调整\r\n if (type.includes('e')) {\r\n newWidth = Math.max(props.minWidth, Math.min(w + deltaX, width - x, props.maxWidth || Infinity))\r\n }\r\n if (type.includes('w')) {\r\n const maxWidth = x + w\r\n newWidth = Math.max(props.minWidth, Math.min(w - deltaX, maxWidth, props.maxWidth || Infinity))\r\n newX = Math.max(0, x + w - newWidth)\r\n }\r\n if (type.includes('s')) {\r\n newHeight = Math.max(\r\n props.minHeight,\r\n Math.min(h + deltaY, height - y, props.maxHeight || Infinity)\r\n )\r\n }\r\n if (type.includes('n')) {\r\n const maxHeight = y + h\r\n newHeight = Math.max(\r\n props.minHeight,\r\n Math.min(h - deltaY, maxHeight, props.maxHeight || Infinity)\r\n )\r\n newY = Math.max(0, y + h - newHeight)\r\n }\r\n\r\n // 处理固定比例\r\n if (props.cropMode === 'ratio' && props.aspectRatio) {\r\n const currentAspect = newWidth / newHeight\r\n if (Math.abs(currentAspect - props.aspectRatio) > 0.01) {\r\n if (type.includes('e') || type.includes('w')) {\r\n newHeight = newWidth / props.aspectRatio\r\n if (type.includes('n')) {\r\n newY = y + h - newHeight\r\n }\r\n } else {\r\n newWidth = newHeight * props.aspectRatio\r\n if (type.includes('w')) {\r\n newX = x + w - newWidth\r\n }\r\n }\r\n }\r\n }\r\n\r\n // 边界检查\r\n if (newX + newWidth > width) {\r\n newWidth = width - newX\r\n if (props.cropMode === 'ratio' && props.aspectRatio) {\r\n newHeight = newWidth / props.aspectRatio\r\n }\r\n }\r\n if (newY + newHeight > height) {\r\n newHeight = height - newY\r\n if (props.cropMode === 'ratio' && props.aspectRatio) {\r\n newWidth = newHeight * props.aspectRatio\r\n }\r\n }\r\n\r\n cropArea.value = { x: newX, y: newY, width: newWidth, height: newHeight }\r\n}\r\n\r\n// 鼠标释放\r\nconst handleMouseUp = () => {\r\n isDragging.value = false\r\n isResizing.value = false\r\n dragType.value = ''\r\n document.removeEventListener('mousemove', handleMouseMove)\r\n document.removeEventListener('mouseup', handleMouseUp)\r\n}\r\n\r\n// 缩放变化\r\nconst handleZoomChange = () => {\r\n // 缩放时保持裁剪区域相对位置\r\n // 这里可以添加更复杂的缩放逻辑\r\n}\r\n\r\n// 鼠标滚轮缩放(电脑端优化)\r\nconst handleWheel = (e: WheelEvent) => {\r\n if (!props.zoomable || !imageLoaded.value) return\r\n\r\n e.preventDefault()\r\n const delta = e.deltaY > 0 ? -0.1 : 0.1\r\n const newZoom = Math.max(minZoom.value, Math.min(maxZoom.value, zoom.value + delta))\r\n zoom.value = Math.round(newZoom * 10) / 10\r\n}\r\n\r\n// 旋转图片\r\nconst rotateImage = (angle: number) => {\r\n rotation.value = (rotation.value + angle) % 360\r\n nextTick(() => {\r\n updateImageDisplaySize()\r\n initCropArea()\r\n })\r\n}\r\n\r\n// 执行裁剪\r\nconst handleCrop = () => {\r\n if (!imageRef.value || !props.imageSrc) return\r\n\r\n const canvas = document.createElement('canvas')\r\n const ctx = canvas.getContext('2d')\r\n if (!ctx) return\r\n\r\n // 1. 获取缩放比例(显示尺寸 vs 原始尺寸)\r\n const scaleX = imageNaturalWidth.value / imageDisplayWidth.value\r\n const scaleY = imageNaturalHeight.value / imageDisplayHeight.value\r\n\r\n // 2. 计算裁剪框在原始图片坐标系下的尺寸(不计旋转)\r\n const { x, y, width, height } = cropArea.value\r\n const cropW = width * scaleX\r\n const cropH = height * scaleY\r\n\r\n // 3. 设置目标 Canvas 尺寸\r\n // 注意:如果旋转了 90/270 度,裁剪结果的视觉尺寸应该互换\r\n const is90Deg = Math.abs(rotation.value % 180) === 90\r\n canvas.width = is90Deg ? cropH : cropW\r\n canvas.height = is90Deg ? cropW : cropH\r\n\r\n ctx.save()\r\n\r\n // 4. 将画布原点移至中心并旋转\r\n ctx.translate(canvas.width / 2, canvas.height / 2)\r\n ctx.rotate((rotation.value * Math.PI) / 180)\r\n\r\n // 5. 关键步骤:计算图片在旋转后的画布上应该绘制的位置\r\n // 我们需要将图片的“裁剪框中心点”对齐到画布的“中心点”\r\n const imgCenterX = imageNaturalWidth.value / 2\r\n const imgCenterY = imageNaturalHeight.value / 2\r\n const cropCenterX = (x + width / 2) * scaleX\r\n const cropCenterY = (y + height / 2) * scaleY\r\n\r\n // 绘制偏移量 = 图片中心 - 裁剪框中心\r\n const drawOffsetX = imgCenterX - cropCenterX\r\n const drawOffsetY = imgCenterY - cropCenterY\r\n\r\n // 6. 绘制图片\r\n ctx.drawImage(\r\n imageRef.value,\r\n -imageNaturalWidth.value / 2 + drawOffsetX,\r\n -imageNaturalHeight.value / 2 + drawOffsetY,\r\n imageNaturalWidth.value,\r\n imageNaturalHeight.value\r\n )\r\n\r\n ctx.restore()\r\n\r\n // 7. 输出结果\r\n canvas.toBlob(blob => {\r\n if (blob) {\r\n const dataUrl = canvas.toDataURL('image/png')\r\n emit('crop', {\r\n blob,\r\n dataUrl,\r\n cropArea: {\r\n x: x * scaleX,\r\n y: y * scaleY,\r\n width: cropW,\r\n height: cropH,\r\n },\r\n })\r\n }\r\n }, 'image/png')\r\n}\r\n\r\n// 取消\r\nconst handleCancel = () => {\r\n emit('cancel')\r\n}\r\n\r\n// 监听图片源变化\r\nwatch(\r\n () => props.imageSrc,\r\n (newSrc: string | undefined) => {\r\n if (newSrc) {\r\n imageLoaded.value = false\r\n rotation.value = 0\r\n zoom.value = props.initialZoom\r\n }\r\n }\r\n)\r\n\r\n// 监听容器大小变化\r\nconst resizeObserver = ref<ResizeObserver | null>(null)\r\n\r\n// 键盘快捷键处理(电脑端优化)\r\nconst handleKeyDown = (e: KeyboardEvent) => {\r\n // 只在组件可见且有图片时响应\r\n if (!imageLoaded.value || !props.imageSrc) return\r\n // 如果用户在输入框中,不响应快捷键\r\n const target = e.target as HTMLElement\r\n if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable)\r\n return\r\n\r\n // Ctrl/Cmd + 滚轮缩放,或方向键旋转\r\n if (e.ctrlKey || e.metaKey) {\r\n if (e.key === '=' || e.key === '+') {\r\n e.preventDefault()\r\n const newZoom = Math.min(maxZoom.value, zoom.value + 0.1)\r\n zoom.value = Math.round(newZoom * 10) / 10\r\n } else if (e.key === '-' || e.key === '_') {\r\n e.preventDefault()\r\n const newZoom = Math.max(minZoom.value, zoom.value - 0.1)\r\n zoom.value = Math.round(newZoom * 10) / 10\r\n }\r\n }\r\n\r\n // R 键旋转(需要组件获得焦点)\r\n if (props.rotatable && (e.key === 'r' || e.key === 'R')) {\r\n e.preventDefault()\r\n rotateImage(90)\r\n }\r\n\r\n // Enter 确认裁剪\r\n if (e.key === 'Enter' && !e.shiftKey) {\r\n e.preventDefault()\r\n handleCrop()\r\n }\r\n\r\n // Esc 取消\r\n if (e.key === 'Escape') {\r\n e.preventDefault()\r\n handleCancel()\r\n }\r\n}\r\n\r\nonMounted(() => {\r\n if (containerRef.value && window.ResizeObserver) {\r\n resizeObserver.value = new ResizeObserver(() => {\r\n updateImageDisplaySize()\r\n })\r\n resizeObserver.value.observe(containerRef.value)\r\n }\r\n\r\n // 添加键盘事件监听(电脑端优化)\r\n document.addEventListener('keydown', handleKeyDown)\r\n})\r\n\r\nonBeforeUnmount(() => {\r\n handleMouseUp()\r\n if (resizeObserver.value) {\r\n resizeObserver.value.disconnect()\r\n }\r\n // 移除键盘事件监听\r\n document.removeEventListener('keydown', handleKeyDown)\r\n})\r\n</script>\r\n\r\n<script lang=\"ts\">\r\nexport default {\r\n name: 'VcImageCropper',\r\n}\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.vc-image-cropper {\r\n position: relative;\r\n background: #1a1a1a;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n user-select: none;\r\n outline: none;\r\n\r\n &:focus {\r\n box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.5);\r\n }\r\n}\r\n\r\n.vc-image-cropper-placeholder {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n color: #666;\r\n}\r\n\r\n.placeholder-content {\r\n text-align: center;\r\n\r\n svg {\r\n margin-bottom: 16px;\r\n opacity: 0.5;\r\n }\r\n\r\n p {\r\n margin: 0;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n.vc-image-cropper-content {\r\n position: relative;\r\n width: 100%;\r\n height: calc(100% - 60px);\r\n overflow: hidden;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.vc-image-wrapper {\r\n position: relative;\r\n transition: transform 0.1s ease-out;\r\n}\r\n\r\n.vc-image-wrapper img {\r\n max-width: none;\r\n max-height: none;\r\n}\r\n\r\n.vc-crop-box {\r\n position: absolute;\r\n border: 2px solid #fff;\r\n box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5);\r\n cursor: move;\r\n}\r\n\r\n.vc-crop-grid {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n pointer-events: none;\r\n}\r\n\r\n.grid-line {\r\n position: absolute;\r\n background: rgba(255, 255, 255, 0.3);\r\n\r\n &.grid-line-h1 {\r\n top: 33.33%;\r\n left: 0;\r\n width: 100%;\r\n height: 1px;\r\n }\r\n\r\n &.grid-line-h2 {\r\n top: 66.66%;\r\n left: 0;\r\n width: 100%;\r\n height: 1px;\r\n }\r\n\r\n &.grid-line-v1 {\r\n left: 33.33%;\r\n top: 0;\r\n width: 1px;\r\n height: 100%;\r\n }\r\n\r\n &.grid-line-v2 {\r\n left: 66.66%;\r\n top: 0;\r\n width: 1px;\r\n height: 100%;\r\n }\r\n}\r\n\r\n.vc-crop-handle {\r\n position: absolute;\r\n width: 8px;\r\n height: 8px;\r\n background: #fff;\r\n border: 1px solid #333;\r\n box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);\r\n z-index: 10;\r\n\r\n &:hover {\r\n background: #667eea;\r\n border-color: #667eea;\r\n }\r\n}\r\n\r\n.vc-cropper-toolbar {\r\n position: absolute;\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n height: 60px;\r\n background: rgba(0, 0, 0, 0.8);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 24px;\r\n padding: 0 24px;\r\n backdrop-filter: blur(10px);\r\n}\r\n\r\n.toolbar-group {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n}\r\n\r\n.toolbar-label {\r\n color: #fff;\r\n font-size: 14px;\r\n white-space: nowrap;\r\n}\r\n\r\n.toolbar-slider {\r\n width: 150px;\r\n height: 4px;\r\n border-radius: 2px;\r\n background: #333;\r\n outline: none;\r\n -webkit-appearance: none;\r\n appearance: none;\r\n\r\n &::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n appearance: none;\r\n width: 16px;\r\n height: 16px;\r\n border-radius: 50%;\r\n background: #667eea;\r\n cursor: pointer;\r\n }\r\n\r\n &::-moz-range-thumb {\r\n width: 16px;\r\n height: 16px;\r\n border-radius: 50%;\r\n background: #667eea;\r\n cursor: pointer;\r\n border: none;\r\n }\r\n}\r\n\r\n.toolbar-value {\r\n color: #fff;\r\n font-size: 14px;\r\n min-width: 40px;\r\n text-align: right;\r\n}\r\n\r\n.toolbar-btn {\r\n padding: 8px 16px;\r\n border: 1px solid #444;\r\n background: #333;\r\n color: #fff;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n transition: all 0.2s;\r\n\r\n &:hover {\r\n background: #444;\r\n border-color: #667eea;\r\n }\r\n\r\n &.toolbar-btn-primary {\r\n background: #667eea;\r\n border-color: #667eea;\r\n\r\n &:hover {\r\n background: #5568d3;\r\n }\r\n }\r\n}\r\n</style>\r\n","import type { App, Component } from 'vue'\r\nimport ScaleContainer from './components/ScaleContainer/index.vue'\r\nimport ImageCropper from './components/ImageCropper/index.vue'\r\n\r\nconst components: Component[] = [\r\n ScaleContainer,\r\n ImageCropper\r\n]\r\n\r\nexport const install = (app: App) => {\r\n components.forEach(component => {\r\n const name = (component as any).name || (component as any).__name\r\n if (name) {\r\n app.component(name, component)\r\n }\r\n })\r\n}\r\n\r\nexport default {\r\n install\r\n}\r\n","// 工具函数\r\nexport const isString = (val: unknown): val is string => typeof val === 'string'\r\n\r\nexport const isNumber = (val: unknown): val is number => typeof val === 'number'\r\n\r\nexport const isBoolean = (val: unknown): val is boolean => typeof val === 'boolean'\r\n\r\nexport const isObject = (val: unknown): val is Record<string, any> =>\r\n val !== null && typeof val === 'object'\r\n\r\nexport const isArray = (val: unknown): val is Array<any> => Array.isArray(val)\r\n\r\nexport const isFunction = (val: unknown): val is Function => typeof val === 'function'\r\n\r\n// 防抖函数\r\nexport function debounce<T extends (...args: any[]) => any>(\r\n func: T,\r\n wait: number\r\n): (...args: Parameters<T>) => void {\r\n let timeout: ReturnType<typeof setTimeout> | null = null\r\n return function (this: any, ...args: Parameters<T>) {\r\n const context = this\r\n if (timeout) clearTimeout(timeout)\r\n timeout = setTimeout(() => {\r\n func.apply(context, args)\r\n }, wait)\r\n }\r\n}\r\n\r\n// 节流函数\r\nexport function throttle<T extends (...args: any[]) => any>(\r\n func: T,\r\n wait: number\r\n): (...args: Parameters<T>) => void {\r\n let timeout: ReturnType<typeof setTimeout> | null = null\r\n let previous = 0\r\n return function (this: any, ...args: Parameters<T>) {\r\n const now = Date.now()\r\n const remaining = wait - (now - previous)\r\n if (remaining <= 0 || remaining > wait) {\r\n if (timeout) {\r\n clearTimeout(timeout)\r\n timeout = null\r\n }\r\n previous = now\r\n func.apply(this, args)\r\n } else if (!timeout) {\r\n timeout = setTimeout(() => {\r\n previous = Date.now()\r\n timeout = null\r\n func.apply(this, args)\r\n }, remaining)\r\n }\r\n }\r\n}\r\n\r\n","// 主入口文件\r\nimport type { App } from 'vue'\r\nimport { install as installComponents } from './install'\r\n\r\n// 导出所有组件\r\nexport * from './components'\r\n\r\n// 导出类型\r\nexport * from './types'\r\n\r\n// 导出工具函数\r\nexport * from './utils'\r\n\r\n// 安装函数(用于 Vue.use())\r\nexport const install = (app: App) => {\r\n installComponents(app)\r\n}\r\n\r\n// 默认导出\r\nexport default {\r\n install\r\n}\r\n\r\n// 版本号\r\nexport const version = '1.0.0'\r\n\r\n"],"names":["_createElementBlock","_createElementVNode","_renderSlot","_openBlock","_Fragment","_renderList","index","_normalizeClass","_normalizeStyle","_toDisplayString","install","installComponents"],"mappings":"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"}
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.vc-scale-container[data-v-7f878606]{margin:0;padding:0;display:block}.vc-scale-wrapper[data-v-7f878606]{box-sizing:border-box;display:block}.vc-image-cropper[data-v-a3fe50be]{position:relative;background:#1a1a1a;border-radius:8px;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;user-select:none;outline:none}.vc-image-cropper[data-v-a3fe50be]:focus{box-shadow:0 0 0 2px #667eea80}.vc-image-cropper-placeholder[data-v-a3fe50be]{display:flex;align-items:center;justify-content:center;height:100%;color:#666}.placeholder-content[data-v-a3fe50be]{text-align:center}.placeholder-content svg[data-v-a3fe50be]{margin-bottom:16px;opacity:.5}.placeholder-content p[data-v-a3fe50be]{margin:0;font-size:14px}.vc-image-cropper-content[data-v-a3fe50be]{position:relative;width:100%;height:calc(100% - 60px);overflow:hidden;display:flex;align-items:center;justify-content:center}.vc-image-wrapper[data-v-a3fe50be]{position:relative;transition:transform .1s ease-out}.vc-image-wrapper img[data-v-a3fe50be]{max-width:none;max-height:none}.vc-crop-box[data-v-a3fe50be]{position:absolute;border:2px solid #fff;box-shadow:0 0 0 9999px #00000080;cursor:move}.vc-crop-grid[data-v-a3fe50be]{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.grid-line[data-v-a3fe50be]{position:absolute;background:#ffffff4d}.grid-line.grid-line-h1[data-v-a3fe50be]{top:33.33%;left:0;width:100%;height:1px}.grid-line.grid-line-h2[data-v-a3fe50be]{top:66.66%;left:0;width:100%;height:1px}.grid-line.grid-line-v1[data-v-a3fe50be]{left:33.33%;top:0;width:1px;height:100%}.grid-line.grid-line-v2[data-v-a3fe50be]{left:66.66%;top:0;width:1px;height:100%}.vc-crop-handle[data-v-a3fe50be]{position:absolute;width:8px;height:8px;background:#fff;border:1px solid #333;box-shadow:0 0 2px #00000080;z-index:10}.vc-crop-handle[data-v-a3fe50be]:hover{background:#667eea;border-color:#667eea}.vc-cropper-toolbar[data-v-a3fe50be]{position:absolute;bottom:0;left:0;right:0;height:60px;background:#000c;display:flex;align-items:center;justify-content:center;gap:24px;padding:0 24px;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.toolbar-group[data-v-a3fe50be]{display:flex;align-items:center;gap:12px}.toolbar-label[data-v-a3fe50be]{color:#fff;font-size:14px;white-space:nowrap}.toolbar-slider[data-v-a3fe50be]{width:150px;height:4px;border-radius:2px;background:#333;outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.toolbar-slider[data-v-a3fe50be]::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background:#667eea;cursor:pointer}.toolbar-slider[data-v-a3fe50be]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:#667eea;cursor:pointer;border:none}.toolbar-value[data-v-a3fe50be]{color:#fff;font-size:14px;min-width:40px;text-align:right}.toolbar-btn[data-v-a3fe50be]{padding:8px 16px;border:1px solid #444;background:#333;color:#fff;border-radius:4px;cursor:pointer;font-size:14px;transition:all .2s}.toolbar-btn[data-v-a3fe50be]:hover{background:#444;border-color:#667eea}.toolbar-btn.toolbar-btn-primary[data-v-a3fe50be]{background:#667eea;border-color:#667eea}.toolbar-btn.toolbar-btn-primary[data-v-a3fe50be]:hover{background:#5568d3}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../components/ScaleContainer/types';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const isString: (val: unknown) => val is string;
|
|
2
|
+
export declare const isNumber: (val: unknown) => val is number;
|
|
3
|
+
export declare const isBoolean: (val: unknown) => val is boolean;
|
|
4
|
+
export declare const isObject: (val: unknown) => val is Record<string, any>;
|
|
5
|
+
export declare const isArray: (val: unknown) => val is Array<any>;
|
|
6
|
+
export declare const isFunction: (val: unknown) => val is Function;
|
|
7
|
+
export declare function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void;
|
|
8
|
+
export declare function throttle<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void;
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "v3-comf-dm",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A Vue3 component library",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.esm.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"private": false,
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/index.esm.js",
|
|
13
|
+
"require": "./dist/index.cjs",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
},
|
|
16
|
+
"./style": "./dist/style.css"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"packages"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"dev": "vite",
|
|
24
|
+
"build": "vite build",
|
|
25
|
+
"build:watch": "vite build --watch",
|
|
26
|
+
"test": "vitest",
|
|
27
|
+
"test:ui": "vitest --ui",
|
|
28
|
+
"test:coverage": "vitest --coverage",
|
|
29
|
+
"lint": "eslint . --ext .vue,.js,.ts",
|
|
30
|
+
"format": "prettier --write \"**/*.{js,ts,json,vue,scss,css}\"",
|
|
31
|
+
"prepublishOnly": "npm run build",
|
|
32
|
+
"publish:npm": "npm publish --registry=https://registry.npmjs.org/ --access public"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public",
|
|
36
|
+
"registry": "https://registry.npmjs.org/"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"vue",
|
|
40
|
+
"vue3",
|
|
41
|
+
"component",
|
|
42
|
+
"library",
|
|
43
|
+
"ui"
|
|
44
|
+
],
|
|
45
|
+
"author": "adqw",
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
49
|
+
"@vitest/ui": "^1.0.0",
|
|
50
|
+
"@vue/test-utils": "^2.4.0",
|
|
51
|
+
"autoprefixer": "^10.4.16",
|
|
52
|
+
"eslint": "^8.54.0",
|
|
53
|
+
"eslint-plugin-vue": "^9.18.1",
|
|
54
|
+
"jsdom": "^23.0.1",
|
|
55
|
+
"postcss": "^8.4.32",
|
|
56
|
+
"prettier": "^3.1.0",
|
|
57
|
+
"sass-embedded": "^1.69.5",
|
|
58
|
+
"terser": "^5.44.1",
|
|
59
|
+
"typescript": "^5.3.2",
|
|
60
|
+
"vite": "^5.0.5",
|
|
61
|
+
"vite-plugin-dts": "^3.6.4",
|
|
62
|
+
"vitest": "^1.0.0",
|
|
63
|
+
"vue": "^3.3.11"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"vue": "^3.0.0"
|
|
67
|
+
}
|
|
68
|
+
}
|