-
-
Save DCdafan/67c2bc70f389ee4f7d7041c0970f3f85 to your computer and use it in GitHub Desktop.
vue+svg 实现缩放
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> | |
| <svg width="800px" height="800px" version="1.1" | |
| xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800"> | |
| <g class="port_output" style="pointer-events: all;"> | |
| <rect fill="#fff" stroke-width="1.5" | |
| :x="selectedItem.x" :y="selectedItem.y" | |
| :width="selectedItem.width" :height="selectedItem.height" | |
| :transform="transform" | |
| style="vector-effect: non-scaling-stroke" | |
| class="port" @click="pointClick" stroke-dasharray="none" stroke="#000"></rect> | |
| <!--<rect x="200" y="200" width="100" height="100" class="port" @click="pointClick"></rect>--> | |
| <!--<rect x="400" y="200" width="100" transform="scale(1.5,1.5)" height="100" class="port" @click="pointClick"></rect>--> | |
| </g> | |
| <path :d="item" stroke="red" stroke-width="2" fill="none" v-for="(item,index) in listData" | |
| :key="index"></path> | |
| <path :d="pathPosition" stroke="blue" stroke-width="1" fill="none"></path> | |
| <g class="selected"> | |
| <circle :cx="itemPosition.cw.value.x" :cy="itemPosition.cw.value.y" r="2.5" | |
| stroke="blue" fill="white"></circle> | |
| <circle :cx="itemPosition.ce.value.x" :cy="itemPosition.ce.value.y" r="2.5" | |
| stroke="blue" fill="white"></circle> | |
| <rect style="cursor:nw-resize" | |
| :x="itemPosition.nw.value.x - 2.5" :y="itemPosition.nw.value.y - 2.5" | |
| stroke="blue" fill="white" | |
| width="5" height="5" | |
| class="port" | |
| @mousedown="shapeScale($event,type='nw')" | |
| ></rect> | |
| <rect style="cursor:ne-resize" | |
| :x="itemPosition.ne.value.x - 2.5" :y="itemPosition.ne.value.y - 2.5" | |
| stroke="blue" fill="white" | |
| width="5" height="5" | |
| class="port" | |
| @mousedown="shapeScale($event,type='ne')" | |
| ></rect> | |
| <rect style="cursor:sw-resize" | |
| :x="itemPosition.sw.value.x - 2.5" :y="itemPosition.sw.value.y - 2.5" | |
| stroke="blue" fill="white" | |
| width="5" height="5" | |
| class="port" | |
| @mousedown="shapeScale($event,type='sw')" | |
| ></rect> | |
| <rect style="cursor:se-resize" | |
| :x="itemPosition.se.value.x - 2.5" :y="itemPosition.se.value.y - 2.5" | |
| stroke="blue" fill="white" | |
| width="5" height="5" | |
| class="port" | |
| @mousedown="shapeScale($event,type='se')" | |
| ></rect> | |
| <rect :x="itemPosition.c.value.x - 2.5" :y="itemPosition.c.value.y - 2.5" | |
| stroke="blue" fill="white" | |
| width="5" height="5" | |
| class="port" | |
| @mousedown="shapeScale" | |
| ></rect> | |
| </g> | |
| </svg> | |
| </template> | |
| <script> | |
| import * as d3 from 'd3'; | |
| export default { | |
| name: 'home', | |
| data() { | |
| return { | |
| listData: { | |
| '001': 'M1,2L30,40', | |
| }, | |
| clickPoint: { | |
| x: '', | |
| y: '' | |
| }, | |
| itemPosition: { | |
| nw: { | |
| name: '', | |
| value: { | |
| x: '', | |
| y: '' | |
| } | |
| }, | |
| sw: { | |
| name: '', | |
| value: { | |
| x: '', | |
| y: '' | |
| } | |
| }, | |
| ne: { | |
| name: '', | |
| value: { | |
| x: '', | |
| y: '' | |
| } | |
| }, | |
| se: { | |
| name: '', | |
| value: { | |
| x: '', | |
| y: '' | |
| } | |
| }, | |
| cw: { | |
| name: '', | |
| value: { | |
| x: '0', | |
| y: '0' | |
| } | |
| }, | |
| ce: { | |
| name: '', | |
| value: { | |
| x: '0', | |
| y: '0' | |
| } | |
| }, | |
| c: { | |
| name: '', | |
| value: { | |
| x: '', | |
| y: '' | |
| } | |
| } | |
| }, | |
| pathPosition: "", | |
| selectedItem: { | |
| target:null, | |
| width:150, | |
| height:150, | |
| x:500, | |
| y:100, | |
| translateX:'', | |
| translateY:'' | |
| }, | |
| scaleValue: { | |
| x: 1, | |
| y: 1 | |
| }, | |
| transform:'' | |
| } | |
| }, | |
| computed: { | |
| }, | |
| mounted() { | |
| }, | |
| methods: { | |
| pointClick(e) { | |
| this.selectedItem.target = e.target; | |
| this.drawSelectPoint() | |
| }, | |
| drawSelectPoint(){ | |
| const pos = this.selectedItem.target.getBoundingClientRect() | |
| // console.log(this.selectedItem.getBBox()) | |
| //左上角 | |
| this.itemPosition.nw = { | |
| name: 'nw', | |
| value: { | |
| x: pos.left, | |
| y: pos.top | |
| } | |
| } | |
| //左下角 | |
| this.itemPosition.sw = { | |
| name: 'sw', | |
| value: { | |
| x: pos.left, | |
| y: pos.top + pos.height | |
| } | |
| } | |
| //右上角 | |
| this.itemPosition.ne = { | |
| name: 'ne', | |
| value: { | |
| x: pos.left + pos.width, | |
| y: pos.top | |
| } | |
| } | |
| //右下角 | |
| this.itemPosition.se = { | |
| name: 'se', | |
| value: { | |
| x: pos.left + pos.width, | |
| y: pos.top + pos.height | |
| } | |
| } | |
| //左中角 | |
| this.itemPosition.cw = { | |
| name: 'cw', | |
| value: { | |
| x: pos.left, | |
| y: pos.top + (pos.height / 2) | |
| } | |
| } | |
| //右中角 | |
| this.itemPosition.ce = { | |
| name: 'ce', | |
| value: { | |
| x: pos.left + pos.width, | |
| y: pos.top + (pos.height / 2) | |
| } | |
| } | |
| //中心点 | |
| this.itemPosition.c = { | |
| name: 'c', | |
| value: { | |
| x: pos.left + (pos.width / 2), | |
| y: pos.top + (pos.height / 2) | |
| } | |
| } | |
| this.drawSelectLine() | |
| }, | |
| drawSelectLine(){ | |
| const path = d3.path() | |
| path.moveTo(this.itemPosition.nw.value.x, this.itemPosition.nw.value.y) | |
| path.lineTo(this.itemPosition.ne.value.x, this.itemPosition.ne.value.y) | |
| path.lineTo(this.itemPosition.se.value.x, this.itemPosition.se.value.y) | |
| path.lineTo(this.itemPosition.sw.value.x, this.itemPosition.sw.value.y) | |
| path.lineTo(this.itemPosition.nw.value.x, this.itemPosition.nw.value.y) | |
| this.pathPosition = path.toString() | |
| }, | |
| pointDown(e) { | |
| this.clickPoint.x = e.offsetX | |
| this.clickPoint.y = e.offsetY | |
| document.onmousemove = (e) => { | |
| this.drawLine(this.clickPoint.x, this.clickPoint.y, e.offsetX, e.offsetY, '002') | |
| }; | |
| document.onmouseup = () => { | |
| document.onmousemove = null; | |
| document.onmouseup = null; | |
| }; | |
| }, | |
| drawLine(x1, y1, x2, y2, id) { | |
| const path = d3.path() | |
| path.moveTo(x1, y1) | |
| path.bezierCurveTo(x2, y1, x1, y2, x2, y2); | |
| // path.lineTo(x2,y2) | |
| this.$set(this.listData, id, path.toString()) | |
| console.log(this.listData) | |
| }, | |
| shapeScale(e,type) { | |
| const target = this.selectedItem.target.getBoundingClientRect() | |
| this.selectedItem.width = target.width | |
| this.selectedItem.height = target.height | |
| if(type === 'nw'){ | |
| const tx = this.selectedItem.x + this.selectedItem.width | |
| const ty = this.selectedItem.y + this.selectedItem.height | |
| this.scaleFunc(e,tx,ty,()=>{ | |
| this.selectedItem.x = this.selectedItem.translateX - this.selectedItem.width | |
| this.selectedItem.y = this.selectedItem.translateY - this.selectedItem.height | |
| }) | |
| } | |
| if(type === 'ne'){ | |
| const tx = this.selectedItem.x | |
| const ty = this.selectedItem.y + this.selectedItem.height | |
| this.scaleFunc(e,tx,ty,()=>{ | |
| this.selectedItem.x = this.selectedItem.translateX | |
| this.selectedItem.y = this.selectedItem.translateY - this.selectedItem.height | |
| }) | |
| } | |
| if(type === 'sw'){ | |
| const tx = this.selectedItem.x + this.selectedItem.width | |
| const ty = this.selectedItem.y | |
| this.scaleFunc(e,tx,ty,()=>{ | |
| this.selectedItem.x = this.selectedItem.translateX - this.selectedItem.width | |
| this.selectedItem.y = this.selectedItem.translateY | |
| }) | |
| } | |
| if(type === 'se'){ | |
| const tx = this.selectedItem.x | |
| const ty = this.selectedItem.y | |
| this.scaleFunc(e,tx,ty,()=>{}) | |
| } | |
| }, | |
| scaleFunc(e,tx,ty,upcall){ | |
| this.selectedItem.translateX = tx | |
| this.selectedItem.translateY = ty | |
| const pos_x = e.clientX - this.selectedItem.translateX | |
| const pos_y = e.clientY - this.selectedItem.translateY | |
| document.onmousemove = (e) => { | |
| const move_x = e.clientX - this.selectedItem.translateX | |
| const move_y = e.clientY - this.selectedItem.translateY | |
| this.scaleValue = { | |
| x: move_x / pos_x, | |
| y: move_y / pos_y | |
| } | |
| this.transform = `translate(${this.selectedItem.translateX},${this.selectedItem.translateY}) scale(${this.scaleValue.x},${this.scaleValue.y}) translate(-${this.selectedItem.translateX},-${this.selectedItem.translateY})` | |
| this.drawSelectPoint() | |
| }; | |
| document.onmouseup = () => { | |
| document.onmousemove = null; | |
| document.onmouseup = null; | |
| this.selectedItem.width = this.selectedItem.width * this.scaleValue.x | |
| this.selectedItem.height = this.selectedItem.height * this.scaleValue.y | |
| this.transform = '' | |
| upcall() | |
| }; | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| :not(svg), :not(foreignObject) > svg { | |
| transform-origin: 0px 0px 0px; | |
| } | |
| </style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment