-
-
Save DCdafan/1a225afb6c32598b4490a0c970a7d97c to your computer and use it in GitHub Desktop.
缩放插件
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <template> | |
| <div class="container"> | |
| <div class="wrap"> | |
| <div class="d1" @mousedown="eleDown" :style="style"> | |
| </div> | |
| </div> | |
| <!--drr--> | |
| <div class="drr" :style="style" :class="{active: active}" ref="drr"> | |
| <div v-if="resizable"> | |
| <div | |
| v-for="name in handle.handles" | |
| class="handle" | |
| :key="name" | |
| :class="'handle-' + name" | |
| :style="{ display: active ? 'block' : 'none', cursor: cursorStyle[name]}" | |
| @mousedown.stop.prevent.self="handleDown(name, $event)" | |
| ></div> | |
| </div> | |
| </div> | |
| </div> | |
| </template> | |
| <script> | |
| export default { | |
| name: 'home', | |
| created(){ | |
| document.documentElement.addEventListener('mousemove', (e) => { | |
| this.flag = true | |
| this.eleHandleMove(e) | |
| }, true) | |
| document.documentElement.addEventListener('mouseup', (e) => { | |
| if (this.flag) { | |
| this.eleUp(e) | |
| } else { | |
| this.dragging = false | |
| this.resizing = false | |
| this.rotating = false | |
| } | |
| document.documentElement.removeEventListener('mousemove', this.eleHandleMove, true) | |
| document.documentElement.removeEventListener('mousedown', this.eleHandleMove, true) | |
| }, true) | |
| }, | |
| computed:{ | |
| style() { //组件样式 | |
| return { | |
| top: this.top + 'px', | |
| left: this.left + 'px', | |
| width: this.width + 'px', | |
| height: this.height + 'px', | |
| transform: 'rotate(' + this.rotate + 'deg)', | |
| zIndex:10, | |
| } | |
| }, | |
| /** | |
| * 根据旋转方向来设置操作条 | |
| * @returns {default.props.cursors|{default, type}|({} & default.props.cursors) | ({} & {default, type})} | |
| */ | |
| cursorStyle() { | |
| const cursors = this.handle.cursors | |
| const names = ['tl', 'tm', 'tr', 'mr', 'br', 'bm', 'bl', 'ml'] | |
| const ARR_LENGTH = 8 | |
| const STEP = 45 | |
| const rotate = this.rotate | |
| const startIndex = rotate ? Math.round(rotate / STEP) : 0 | |
| let newCursors = cursors | |
| if (startIndex > 1) { | |
| newCursors = Object.assign({}, cursors) | |
| names.forEach((v, i) => { | |
| newCursors[v] = cursors[names[(startIndex + i) % ARR_LENGTH]] | |
| }) | |
| } | |
| return newCursors | |
| } | |
| }, | |
| data(){ | |
| return { | |
| active:false, | |
| width:200, | |
| height:200, | |
| top:0, | |
| left:0, | |
| rotate:0, | |
| draggable:true, | |
| dragging:false, | |
| resizable:true, | |
| resizing: false, | |
| rotatable:true, | |
| rotating: false, | |
| container:{ | |
| x:'', | |
| y:'', | |
| w:'', | |
| h:'' | |
| }, | |
| ele:{ | |
| x:'', | |
| y:'', | |
| w:'', | |
| h:'' | |
| }, | |
| current:{ | |
| mouseX:'', | |
| mouseY:'', | |
| centerX:'', | |
| centerY:'', | |
| x:'', | |
| y:'', | |
| w:'', | |
| h:'' | |
| }, | |
| handle:{ | |
| x:'', | |
| y:'', | |
| w:'', | |
| h:'', | |
| name:'', | |
| handles:['tl', 'tm', 'tr', 'mr', 'br', 'bm', 'bl', 'ml', 'rot'], | |
| cursors:{ | |
| tl: 'nwse-resize', | |
| tm: 'ns-resize', | |
| tr: 'nesw-resize', | |
| mr: 'ew-resize', | |
| br: 'nwse-resize', | |
| bm: 'ns-resize', | |
| bl: 'nesw-resize', | |
| ml: 'ew-resize' | |
| } | |
| }, | |
| fixed:{ | |
| xName:'', | |
| yName:'', | |
| x:'', | |
| y:'' | |
| } | |
| } | |
| }, | |
| methods:{ | |
| eleDown(e){ | |
| this.active = true | |
| if (this.draggable) { | |
| this.eleDragDown(e) | |
| } | |
| }, | |
| eleHandleMove(e){ | |
| if (this.dragging) { | |
| this.eleDrag(e) | |
| } | |
| if(this.resizing){ | |
| this.handleResize(e) | |
| } | |
| if(this.rotating){ | |
| this.handleRotate(e) | |
| } | |
| }, | |
| eleUp(e){ | |
| console.log(e) | |
| let {x: mouseX, y: mouseY} = this.getMouseCoordinate(e) | |
| this.current.mouseX = mouseX | |
| this.current.mouseY = mouseY | |
| this.dragging = false | |
| this.resizing = false | |
| this.rotating = false | |
| }, | |
| eleDragDown(e){ | |
| this.dragging = true | |
| let {x: mouseX, y: mouseY} = this.getMouseCoordinate(e) | |
| // 鼠标当前位置 | |
| this.current.mouseX = mouseX | |
| this.current.mouseY = mouseY | |
| this.recordElePosition(e) | |
| this.recordHandlePosition(e) | |
| // 获取父级画布信息 | |
| // this.getContainerInfo() | |
| //记录点击初始位置 | |
| this.current.x = this.ele.x | |
| this.current.y = this.ele.y | |
| }, | |
| eleDrag(e){ | |
| let {x: mouseX, y: mouseY} = this.getMouseCoordinate(e) | |
| let diffX = mouseX - this.current.mouseX | |
| let diffY = mouseY - this.current.mouseY | |
| // 每一次先复原初始位置 | |
| this.ele.x = this.current.x | |
| this.ele.y = this.current.y | |
| this.ele.x += diffX | |
| this.ele.y += diffY | |
| this.left = Math.round(this.ele.x) | |
| this.top = Math.round(this.ele.y) | |
| }, | |
| handleDown(handleName,e){ | |
| this.handleName = handleName | |
| if (e.stopPropagation) e.stopPropagation() | |
| if (e.preventDefault) e.preventDefault() | |
| this.recordHandlePosition() | |
| if (handleName === 'rot') { | |
| this.handleRotateDown(e) | |
| }else{ | |
| this.handleResizeDown(handleName, e) | |
| } | |
| }, | |
| handleResizeDown(handleName,e){ | |
| let {x: mouseX, y: mouseY} = this.getMouseCoordinate(e) | |
| // 鼠标当前位置 | |
| this.current.mouseX = mouseX | |
| this.current.mouseY = mouseY | |
| let fixedName = { | |
| x: handleName[1] === 'l' ? 'right' : 'left', | |
| y: handleName[0] === 't' ? 'bottom' : 'top' | |
| } | |
| let rect = { | |
| top: this.top, | |
| right: this.left + this.width, | |
| bottom: this.top + this.height, | |
| left: this.left | |
| } | |
| // 计算固定点坐标 | |
| let fixedCoordinate = this.rotatedPoint(rect, this.rotate, fixedName) | |
| // 计算固定点名称 | |
| this.fixed.xName = fixedName.x | |
| this.fixed.yName = fixedName.y | |
| // 固定点坐标赋值 | |
| this.fixed.x = fixedCoordinate.x | |
| this.fixed.y = fixedCoordinate.y | |
| this.current.x = this.handle.x | |
| this.current.y = this.handle.y | |
| this.current.w = this.handle.w | |
| this.current.h = this.handle.h | |
| this.resizing = true | |
| }, | |
| handleResize(e){ | |
| if(this.resizing){ | |
| let {x: mouseX, y: mouseY} = this.getMouseCoordinate(e) | |
| let rotate = this.rotate | |
| let width = mouseX - this.current.mouseX | |
| let height = mouseY - this.current.mouseY | |
| let c = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)) | |
| let angle = this.getAngle(width, height) | |
| let rad = Math.PI / 180 * (angle - rotate) | |
| let diffY = Math.round(Math.sin(rad) * c) | |
| let diffX = Math.round(Math.cos(rad) * c) | |
| this.handle.x = this.current.x | |
| this.handle.y = this.current.y | |
| this.handle.w = this.current.w | |
| this.handle.h = this.current.h | |
| // 缩放计算 | |
| let [handleY, handleX] = this.handleName | |
| if (handleX !== 'm') { | |
| this.handle.w += diffX * (handleX === 'r' ? 1 : -1) | |
| } | |
| if (handleY !== 'm') { | |
| this.handle.h += diffY * (handleY === 'b' ? 1 : -1) | |
| } | |
| // 边界处理 | |
| if (this.handle.w < 50) { | |
| this.handle.w = 50 | |
| } | |
| if (this.handle.h < 50) { | |
| this.handle.h = 50 | |
| } | |
| if (this.handle.w < 0) { | |
| this.handle.w = -this.handle.w | |
| this.fixedXExchange = true | |
| } | |
| if (this.handle.h < 0) { | |
| this.handle.h = -this.handle.h | |
| this.fixedYExchange = true | |
| } | |
| this.handleFixed() | |
| this.left = Math.round(this.handle.x) | |
| this.top = Math.round(this.handle.y) | |
| this.width = Math.round(this.handle.w) | |
| this.height = Math.round(this.handle.h) | |
| } | |
| }, | |
| handleRotateDown(e) { | |
| let {x, y, w, h} = this.handle | |
| this.current.centerX = window.pageXOffset + x + w / 2 | |
| this.current.centerY = window.pageYOffset + y + h / 2 | |
| this.rotating = true | |
| }, | |
| handleRotate(e){ | |
| console.log(e) | |
| if(this.rotating){ | |
| let {x: mouseX, y: mouseY} = this.getMouseCoordinate(e) | |
| let x = mouseX - this.current.centerX | |
| let y = mouseY - this.current.centerY | |
| this.rotate = (this.getAngle(x, y) + 90) % 360 | |
| console.log(this.rotate) | |
| } | |
| }, | |
| handleFixed() { | |
| // 获取元素区域 | |
| let rect = { | |
| top: this.handle.y, | |
| right: this.handle.x + this.handle.w, | |
| bottom: this.handle.y + this.handle.h, | |
| left: this.handle.x | |
| } | |
| let fixedXName, fixedYName | |
| if (this.fixedXExchange) { | |
| fixedXName = this.fixed.xName === 'right' ? 'left' : 'right' | |
| } else { | |
| fixedXName = this.fixed.xName | |
| } | |
| if (this.fixedYExchange) { | |
| fixedYName = this.fixed.yName === 'top' ? 'bottom' : 'top' | |
| } else { | |
| fixedYName = this.fixed.yName | |
| } | |
| let fixed = { | |
| x: fixedXName, | |
| y: fixedYName | |
| } | |
| let {x: fixedX, y: fixedY} = this.rotatedPoint(rect, this.rotate, fixed) | |
| let dX = Math.round(this.fixed.x - fixedX) | |
| let dY = Math.round(this.fixed.y - fixedY) | |
| this.handle.x += dX | |
| this.handle.y += dY | |
| }, | |
| /** | |
| * 获取元素基本信息 | |
| */ | |
| recordElePosition(e){ | |
| const info = e.target | |
| this.ele.x = parseInt(info.style.left) | |
| this.ele.y = parseInt(info.style.top) | |
| this.ele.w = info.offsetWidth ||info.clientWidth | |
| this.ele.h = info.offsetHeight || info.clientHeight | |
| }, | |
| /** | |
| * 获取操作条基本信息 | |
| */ | |
| recordHandlePosition(){ | |
| const info = this.$refs.drr | |
| this.handle.x = parseInt(info.style.left) | |
| this.handle.y = parseInt(info.style.top) | |
| this.handle.w = info.offsetWidth ||info.clientWidth | |
| this.handle.h = info.offsetHeight || info.clientHeight | |
| }, | |
| /** | |
| * 获取鼠标位置 | |
| * @param e | |
| * @returns {*} | |
| */ | |
| getMouseCoordinate(e) { | |
| return { | |
| x: e.pageX || e.clientX + document.documentElement.scrollLeft, | |
| y: e.pageY || e.clientY + document.documentElement.scrollTop | |
| } | |
| }, | |
| /** | |
| * 旋转点计算 | |
| * @param rect | |
| * @param rotate | |
| * @param point | |
| * @returns {{x: *, y: *}} | |
| */ | |
| rotatedPoint(rect, rotate, point) { | |
| let {top, right, bottom, left} = rect | |
| let rad = Math.PI / 180 * rotate | |
| let cos = Math.cos(rad) | |
| let sin = Math.sin(rad) | |
| let originX = (right - left + 1) / 2 + left | |
| let originY = (bottom - top + 1) / 2 + top | |
| let x = rect[point.x] | |
| let y = rect[point.y] | |
| x -= originX | |
| y -= originY | |
| return { | |
| x: x * cos - y * sin + originX, | |
| y: x * sin + y * cos + originY | |
| } | |
| }, | |
| /** | |
| * 旋转角度 | |
| * @param x | |
| * @param y | |
| * @returns {number} | |
| */ | |
| getAngle(x, y) { | |
| let theta = Math.atan2(y, x) // range (-PI, PI] | |
| theta = Math.round(180 / Math.PI * theta) // rads to degs, range (-180, 180] | |
| if (theta < 0) theta = 360 + theta // range [0, 360) | |
| return theta | |
| }, | |
| } | |
| } | |
| </script> | |
| <style> | |
| .container{ | |
| position: fixed; | |
| top:0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .wrap{ | |
| position: relative; | |
| width:800px; | |
| height:600px; | |
| background-color: #5B6B73; | |
| } | |
| .d1{ | |
| position: absolute; | |
| top: 116px; | |
| left: 128px; | |
| width: 160px; | |
| height: 160px; | |
| z-index: 7; | |
| background-color: #108ee9; | |
| } | |
| .d2{ | |
| position: absolute; | |
| top: 216px; | |
| left: 328px; | |
| width: 200px; | |
| height: 200px; | |
| z-index: 8; | |
| background-color: #108ee9; | |
| } | |
| /*drr*/ | |
| .drr { | |
| position: absolute; | |
| box-sizing: border-box; | |
| display: none; | |
| pointer-events: none; | |
| } | |
| .drr.dragging { | |
| user-select: none; | |
| } | |
| .drr.active{ | |
| display: block; | |
| } | |
| .drr.active:before { | |
| content: ''; | |
| position: absolute; | |
| top: -1px; | |
| right: -1px; | |
| bottom: -1px; | |
| left: -1px; | |
| border: 1px solid #f00; | |
| z-index: -1; | |
| } | |
| .handle { | |
| box-sizing: border-box; | |
| display: none; | |
| position: absolute; | |
| width: 10px; | |
| height: 10px; | |
| font-size: 1px; | |
| border-radius: 5px; | |
| background: #eee; | |
| border: 1px solid #1baee1; | |
| z-index: 100; | |
| pointer-events: auto; | |
| } | |
| .handle-tl { | |
| top: -5px; | |
| left: -5px; | |
| } | |
| .handle-tm { | |
| top: -5px; | |
| left: 50%; | |
| margin-left: -5px; | |
| } | |
| .handle-tr { | |
| top: -5px; | |
| right: -5px; | |
| } | |
| .handle-ml { | |
| top: 50%; | |
| margin-top: -5px; | |
| left: -5px; | |
| } | |
| .handle-mr { | |
| top: 50%; | |
| margin-top: -5px; | |
| right: -5px; | |
| } | |
| .handle-bl { | |
| bottom: -5px; | |
| left: -5px; | |
| } | |
| .handle-bm { | |
| bottom: -5px; | |
| left: 50%; | |
| margin-left: -5px; | |
| } | |
| .handle-br { | |
| bottom: -5px; | |
| right: -5px; | |
| } | |
| .handle-rot { | |
| position: absolute; | |
| top: 0; | |
| left: 50%; | |
| margin-top: -20px; | |
| width: 10px; | |
| height: 10px; | |
| transform: translate(-50%, 0); | |
| cursor: url(./img/rotate.svg) 20 20, move; | |
| z-index: -1; | |
| pointer-events: auto; | |
| } | |
| </style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment