123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888 |
- <template>
- <div>
- <div style="margin-bottom: 10px">
- <el-button plain type="primary" class="shape-border" @click="drawTypeChange('rectangle')" :disabled="!state.dragMode">标注模式</el-button>
- <el-button plain type="primary" class="shape-border" @click="enableDragMode" :disabled="state.dragMode">移动图片</el-button>
- <el-button plain type="primary" style="margin-left: 30px" class="shape-border" @click="selectLastObject" :disabled="!!state.activeTarget">选择最后一个标注(w)</el-button>
- <el-button
- plain
- type="primary"
- class="shape-border"
- @click="rotate(8)"
- :disabled="!state.activeTarget"
- >
- 顺时针旋转(r)
- </el-button>
- <el-button plain type="primary" class="shape-border" @click="rotate(-8)" :disabled="!state.activeTarget">逆时针旋转(e)</el-button>
- <el-button plain type="primary" style="margin-left: 30px" class="shape-border" @click="changeZoom(1.1)">放大图片</el-button>
- <el-button plain type="primary" class="shape-border" @click="changeZoom(0.9)">缩小图片</el-button>
- <!-- <el-button plain type="primary" class="shape-border" @click="drawPolygon('polygon')">多边形</el-button> -->
- </div>
- <canvas id="canvas" :width="cWidth" :height="cHeight"></canvas>
- </div>
- </template>
- <script lang="ts" setup>
- import { fabric } from 'fabric'
- import { reactive, watch, onMounted } from 'vue'
- import { ElMessage } from 'element-plus'
- // import { sortPoints } from '@/utils/fabric'
- const props = defineProps({
- src: {
- type: String,
- default: ''
- },
- area: {
- type: String,
- default: ''
- },
- width: {
- type: Number,
- default: 1920
- },
- height: {
- type: Number,
- default: 1080
- },
- cWidth: {
- type: Number,
- default: 960
- },
- cHeight: {
- type: Number,
- default: 540
- },
- classDef: {
- type: Object
- },
- jsonData: {
- type: Array
- }
- })
- const state = reactive({
- loading: true,
- radio: 1,
- realRadioX: 0.5,
- realRadioY: 0.5,
- imgPoint: { x: 0, y: 0 },
- realPoint: { x: 0, y: 0 },
- canvas: {} as any,
- mouseFrom: { x: 0, y: 0 } as canvasPoint,
- mouseTo: { x: 0, y: 0 } as canvasPoint,
- dragMode: false,
- isDragging: false,
- lastPosX: 0,
- lastPosY: 0,
- // drawType: 'rectangle' as string, //当前绘制图像的种类
- drawType: null as any, //当前绘制图像的种类
- drawWidth: 5, //笔触宽度
- color: '#E34F51', //画笔颜色
- drawingObject: null as any, //当前绘制对象
- activeTarget: null as any, // 当前点击活跃对象
- moveCount: 1, //绘制移动计数器
- doDrawing: false as boolean, // 绘制状态
- rectPath: '' as string, //矩形绘制路径
- //polygon 相关参数
- polygonMode: false as boolean,
- pointArray: [] as canvasPoint[],
- lineArray: [] as canvasPoint[],
- activeShape: false as any,
- activeLine: '' as any,
- line: {} as canvasPoint
- })
- watch(
- () => props.classDef,
- value => {
- // console.log(value)
- state.color = value && value.color ? value.color : '#E34F51'
- }
- )
- watch(
- () => state.drawType,
- value => {
- // console.log(value)
- state.canvas.selection = !value
- }
- )
- watch(
- () => props.width,
- value => {
- state.canvas.setWidth(value)
- }
- )
- watch(
- () => props.height,
- value => {
- state.canvas.setHeight(value)
- }
- )
- const enableDragMode = () => {
- state.dragMode = true
- state.activeTarget = null
- }
- const changeZoom = multi => {
- // 放大
- state.radio = state.canvas.getZoom() * multi
- state.canvas.setZoom(state.radio)
- // state.canvas.setViewport(state.canvas.getCenter()); // 更新视口
- state.canvas.renderAll()
- }
- const loadInit = () => {
- drawTypeChange('rectangle')
- state.color = props.classDef && props.classDef.color ? props.classDef.color : '#E34F51'
- document.addEventListener('keydown', function (e) {
- if (e.key === 'w' || e.key === 'W') {
- selectLastObject()
- return
- }
- if (state.activeTarget) {
- if (e.key === 'r' || e.key === 'R') {
- // 旋转矩形对象
- state.activeTarget.rotate(state.activeTarget.angle + 5)
- state.canvas.renderAll()
- } else if (e.key === 'e' || e.key === 'E') {
- // 旋转矩形对象
- state.activeTarget.rotate(state.activeTarget.angle - 5)
- state.canvas.renderAll()
- }
- }
- })
- if (props.src == '') {
- return
- }
- state.loading = true
- state.canvas = new fabric.Canvas('canvas', {})
- state.canvas.selectionColor = 'rgba(0,0,0,0.05)'
- state.canvas.on('mouse:down', mousedown)
- state.canvas.on('mouse:move', mousemove)
- state.canvas.on('mouse:up', mouseup)
- // // 添加鼠标滚轮缩放功能
- // state.canvas.on('mouse:wheel', event => {
- // const delta = event.delta
- // const zoom = state.canvas.getZoom()
- // const point = new fabric.Point(event.x, event.y)
- //
- // if (delta > 0) {
- // // 放大
- // state.canvas.zoomToPoint(point, zoom * 1.1)
- // // state.radio *= 1.1
- // } else {
- // // 缩小
- // state.canvas.zoomToPoint(point, zoom * 0.9)
- // // state.radio *= 0.9
- // }
- // state.canvas.renderAll()
- // event.e.preventDefault()
- // event.e.stopPropagation()
- // })
- // nice try!
- // console.log(props.jsonData)
- // if (props.jsonData && props.jsonData.length > 0) {
- // // console.log('load')
- // state.canvas.loadFromJSON(props.jsonData, () => {
- // let objects = state.canvas.getObjects()
- // // console.log(objects)
- // objects[0].selectable = false
- // for (let i = 1; i < objects.length; i++) {
- // objects[i].selectable = true
- // }
- // state.canvas.renderAll()
- // })
- // // console.log(state.canvas)
- // state.loading = false
- // return
- // }
- let imgElement = new Image()
- imgElement.src = props.src
- imgElement.onload = () => {
- // 区域大小/图片原始大小 缩放比例
- state.radio =
- props.cWidth / imgElement.width > props.cHeight / imgElement.height ? props.cHeight / imgElement.height : props.cWidth / imgElement.width
- // console.log('state.radio', state.radio)
- // 屏幕分辨率/图片原始大小
- state.realRadioX = props.width / imgElement.width
- state.realRadioY = props.height / imgElement.height
- state.imgPoint.x = Math.floor(imgElement.width / 2)
- state.imgPoint.y = Math.floor(imgElement.height / 2)
- state.realPoint.x = Math.floor(props.width / 2)
- state.realPoint.y = Math.floor(props.height / 2)
- let imgInstance = new fabric.Image(imgElement, {
- selectable: false,
- width: imgElement.width,
- height: imgElement.height,
- scaleX: state.radio,
- scaleY: state.radio
- })
- state.canvas.add(imgInstance)
- if (props.jsonData && props.jsonData.length > 0) {
- for (let i = 0; i < props.jsonData.length; i++) {
- let config = props.jsonData[i]
- let obj = new fabric.Path(config.pathString, config)
- state.canvas.add(obj)
- }
- state.canvas.renderAll()
- }
- state.radio = state.canvas.getZoom()
- state.loading = false
- // console.log(state.realRadioX)
- // console.log(state.realRadioY)
- }
- }
- // const drawImage = () => {
- // if (props.area === '') {
- // clearAll()
- // return
- // }
- // // console.log(props.area)
- // let points = props.area.split(',').map(item => {
- // let areas = item.split(';')
- // let data = areas.map((ars, index) => {
- // let arp = 0
- // let ar = Number(ars)
- // if (index % 2 == 0) {
- // let dx = Math.abs(state.realPoint.x > ar ? state.realPoint.x - ar : state.realPoint.x + ar) / state.realRadioX
- // let rdx = Math.abs(state.imgPoint.x - dx)
- // arp = rdx
- // } else {
- // let dy = Math.abs(state.realPoint.y > ar ? state.realPoint.y - ar : state.realPoint.y + ar) / state.realRadioY
- // let rdy = Math.abs(state.imgPoint.y - dy)
- // arp = rdy
- // }
- // return Number(arp) * state.radio
- // })
- // return data
- // })
- // points.forEach(point => {
- // drawImageObj(point)
- // })
- // }
- // const drawImageObj = data => {
- // let path = 'M '
- // // debugger
- // let points = [] as any
- // let len = data.length / 2
- // for (let i = 0; i < len; i++) {
- // let idx = i * 2
- // points.push({ x: data[idx], y: data[idx + 1] })
- // path += `${data[idx]} ${data[idx + 1]} L `
- // }
- // let canvasObject = null as any
- // if (points[0]?.y === points[1]?.y && points[2]?.y === points[3]?.y && points[0]?.x === points[3]?.x && points[1]?.x - points[2]?.x) {
- // path = path.replace(/L\s$/g, 'z')
- // canvasObject = new fabric.Path(path, {
- // left: data[0],
- // top: data[1],
- // stroke: state.color,
- // selectable: false,
- // strokeWidth: state.drawWidth,
- // fill: 'rgba(255, 255, 255, 0)',
- // hasControls: false
- // })
- // } else {
- // canvasObject = new fabric.Polygon(points, {
- // stroke: state.color,
- // strokeWidth: state.drawWidth,
- // fill: 'rgba(255, 255, 255, 0)',
- // opacity: 1,
- // hasBorders: false,
- // hasControls: false,
- // evented: false
- // })
- // }
- // canvasObject['points'] = points
- // state.canvas.add(canvasObject)
- // }
- const selectLastObject = () => {
- let objects = state.canvas.getObjects()
- state.activeTarget = objects[objects.length - 1]
- state.activeTarget.set('hasRotatingPoint', true)
- state.canvas.setActiveObject(state.activeTarget)
- state.canvas.renderAll()
- }
- const rotate = val => {
- if (!state.activeTarget) {
- ElMessage.error('请先选择旋转对象!')
- } else {
- state.activeTarget.rotate(state.activeTarget.angle + val)
- state.canvas.renderAll()
- }
- }
- const drawTypeChange = e => {
- state.dragMode = false
- state.activeTarget = null
- state.drawType = e
- state.canvas.skipTargetFind = !!e
- if (e == 'pen') {
- // isDrawingMode为true 才可以自由绘画
- state.canvas.isDrawingMode = true
- } else {
- state.canvas.isDrawingMode = false
- }
- }
- // 鼠标按下时触发
- const mousedown = e => {
- if (state.dragMode) {
- state.isDragging = true
- state.lastPosX = e.e.clientX - state.canvas.getElement().offsetLeft
- state.lastPosY = e.e.clientY - state.canvas.getElement().offsetTop
- return
- }
- // console.log(state.canvas.getObjects()[1])
- // console.log(e)
- const target = e.target
- // console.log(target)
- if (target) {
- if (target.type === 'rect') {
- state.activeTarget = target
- state.activeTarget.set('hasRotatingPoint', true)
- state.canvas.setActiveObject(state.activeTarget)
- return
- } else {
- state.activeTarget = null
- // state.canvas.discardActiveObject()
- }
- }
- // console.log(state.lastPosX, state.lastPosY)
- // console.log(state.canvas.viewportTransform)
- // 记录鼠标按下时的坐标
- let xy = e.pointer || transformMouse(e.e.offsetX, e.e.offsetY)
- // console.log(xy)
- state.mouseFrom.x = (xy.x - state.canvas.viewportTransform[4]) / state.radio
- state.mouseFrom.y = (xy.y - state.canvas.viewportTransform[5]) / state.radio
- state.doDrawing = true
- // console.log(state.drawType)
- // 绘制多边形
- if (state.drawType == 'polygon') {
- state.canvas.skipTargetFind = false
- try {
- // 此段为判断是否闭合多边形,点击红点时闭合多边形
- if (state.pointArray.length > 1) {
- // e.target.id == this.pointArray[0].id 表示点击了初始红点
- if (e.target && e.target.id == state.pointArray[0].id) {
- generatePolygon()
- }
- }
- //未点击红点则继续作画
- if (state.polygonMode) {
- addPoint(e)
- }
- } catch (error) {
- console.log(error)
- }
- }
- }
- // 鼠标松开执行
- const mouseup = e => {
- if (state.dragMode) {
- state.isDragging = false
- return
- }
- if (state.activeTarget) {
- state.activeTarget.setCoords()
- state.canvas.requestRenderAll()
- return
- }
- let xy = e.pointer || transformMouse(e.e.offsetX, e.e.offsetY)
- state.mouseTo.x = (xy.x - state.canvas.viewportTransform[4]) / state.radio
- state.mouseTo.y = (xy.y - state.canvas.viewportTransform[5]) / state.radio
- state.drawingObject = null
- state.moveCount = 1
- if (state.drawType != 'polygon' && state.drawType != 'line') {
- state.doDrawing = false
- }
- // 设置只允许绘制一个
- // let canvasObj = state.canvas.getObjects();
- // if(canvasObj.length >2){
- // state.canvas.remove(canvasObj[1])
- // }
- }
- //鼠标移动过程中已经完成了绘制
- const mousemove = e => {
- if (state.dragMode) {
- if (state.isDragging) {
- const deltaMove = {
- x: e.e.clientX - state.canvas.getElement().offsetLeft - state.lastPosX,
- y: e.e.clientY - state.canvas.getElement().offsetTop - state.lastPosY
- }
- state.lastPosX = e.e.clientX - state.canvas.getElement().offsetLeft
- state.lastPosY = e.e.clientY - state.canvas.getElement().offsetTop
- state.canvas.relativePan(new fabric.Point(deltaMove.x, deltaMove.y))
- // state.canvas.viewportTransform[4] += deltaMove.x
- // state.canvas.viewportTransform[5] += deltaMove.y
- // state.canvas.getObjects().forEach(obj => {
- // if (obj.type !== 'rect') {
- // return
- // }
- // obj.left = (obj.left - state.canvas.viewportTransform[4]) / state.radio;
- // obj.top = (obj.top - state.canvas.viewportTransform[5]) / state.radio;
- // obj.setCoords();
- // obj.setOptions({
- // selectable: true,
- // evented: true
- // });
- // });
- state.canvas.requestRenderAll();
- }
- return
- }
- if (state.activeTarget) {
- // const pointer = state.canvas.getPointer(e.e)
- // state.activeTarget.set({
- // left: pointer.x,
- // top: pointer.y
- // });
- state.canvas.requestRenderAll()
- return
- }
- if (state.moveCount % 2 && !state.doDrawing) {
- //减少绘制频率
- return
- }
- state.moveCount++
- let xy = e.pointer || transformMouse(e.e.offsetX, e.e.offsetY)
- if (xy.y >= 0 && xy.x <= props.cWidth && xy.y >= 0 && xy.y <= props.cHeight) {
- state.mouseTo.x = (xy.x - state.canvas.viewportTransform[4]) / state.radio
- state.mouseTo.y = (xy.y - state.canvas.viewportTransform[5]) / state.radio
- // 矩形
- if (state.drawType == 'rectangle') {
- if (state.mouseFrom.x < state.mouseTo.x && state.mouseFrom.y < state.mouseTo.y) {
- drawing()
- } else {
- // clearAll();
- }
- }
- if (state.drawType == 'polygon') {
- if (state.activeLine && state.activeLine.class == 'line') {
- let pointer = state.canvas.getPointer(e.e)
- state.activeLine.set({ x2: pointer.x, y2: pointer.y })
- let points = state.activeShape.get('points')
- points[state.pointArray.length] = {
- x: pointer.x,
- y: pointer.y,
- zIndex: 1
- }
- state.activeShape.set({
- points: points
- })
- state.canvas.renderAll()
- }
- state.canvas.renderAll()
- }
- } else {
- // clearAll();
- }
- }
- // 绘制矩形
- const drawing = () => {
- if (state.drawingObject) {
- state.canvas.remove(state.drawingObject)
- }
- let canvasObject = null
- let left = state.mouseFrom.x,
- top = state.mouseFrom.y,
- mouseFrom = state.mouseFrom,
- mouseTo = state.mouseTo
- let path =
- 'M ' +
- mouseFrom.x +
- ' ' +
- mouseFrom.y +
- ' L ' +
- mouseTo.x +
- ' ' +
- mouseFrom.y +
- ' L ' +
- mouseTo.x +
- ' ' +
- mouseTo.y +
- ' L ' +
- mouseFrom.x +
- ' ' +
- mouseTo.y +
- ' L ' +
- mouseFrom.x +
- ' ' +
- mouseFrom.y +
- ' z'
- state.rectPath = path
- canvasObject = new fabric.Rect({
- left: left,
- top: top,
- width: Math.abs(mouseTo.x - left),
- height: Math.abs(mouseTo.y - top),
- stroke: state.color,
- strokeWidth: state.drawWidth,
- fill: 'rgba(255, 255, 255, 0)',
- centeredRotation: true,
- angle: 0,
- label: props.classDef.label
- })
- // canvasObject = new fabric.Path(path, {
- // left: left,
- // top: top,
- // stroke: state.color,
- // selectable: false,
- // strokeWidth: state.drawWidth,
- // fill: 'rgba(255, 255, 255, 0)',
- // hasControls: false
- // })
- // console.log(canvasObject)
- canvasObject.on('selected', event => {
- // console.log("selected")
- state.activeTarget = event.target
- })
- if (canvasObject) {
- state.canvas.add(canvasObject)
- state.drawingObject = canvasObject
- }
- }
- // 绘制多边形开始,绘制多边形和其他图形不一样,需要单独处理
- // const drawPolygon = type => {
- // state.drawType = type
- // state.polygonMode = true
- // //这里画的多边形,由顶点与线组成
- // state.pointArray = [] // 顶点集合
- // state.lineArray = [] //线集合
- // state.canvas.isDrawingMode = false
- // }
- const addPoint = e => {
- let random = Math.floor(Math.random() * 10000)
- let id = new Date().getTime() + random
- let circle = new fabric.Circle({
- radius: 5,
- fill: '#ffffff',
- stroke: '#333333',
- strokeWidth: 0.5,
- left: (e.pointer.x || e.e.layerX) / state.canvas.getZoom(),
- top: (e.pointer.y || e.e.layerY) / state.canvas.getZoom(),
- selectable: false,
- hasBorders: false,
- hasControls: false,
- originX: 'center',
- originY: 'center',
- id: id,
- objectCaching: false
- })
- if (state.pointArray.length == 0) {
- circle.set({
- fill: '#00FFFF'
- })
- }
- let points = [
- (e.pointer.x || e.e.layerX) / state.canvas.getZoom(),
- (e.pointer.y || e.e.layerY) / state.canvas.getZoom(),
- (e.pointer.x || e.e.layerX) / state.canvas.getZoom(),
- (e.pointer.y || e.e.layerY) / state.canvas.getZoom()
- ]
- state.line = new fabric.Line(points, {
- strokeWidth: 2,
- fill: '#999999',
- stroke: '#999999',
- class: 'line',
- originX: 'center',
- originY: 'center',
- selectable: false,
- hasBorders: false,
- hasControls: false,
- evented: false,
- objectCaching: false
- })
- if (state.activeShape) {
- let pos = state.canvas.getPointer(e.e)
- let points = state.activeShape.get('points')
- points.push({
- x: pos.x,
- y: pos.y
- })
- let polygon = new fabric.Polygon(points, {
- stroke: '#333333',
- strokeWidth: 1,
- fill: '#cccccc',
- opacity: 0.3,
- selectable: false,
- hasBorders: false,
- hasControls: false,
- evented: false,
- objectCaching: false
- })
- state.canvas.remove(state.activeShape)
- state.canvas.add(polygon)
- state.activeShape = polygon
- state.canvas.renderAll()
- } else {
- let polyPoint = [
- {
- x: (e.pointer.x || e.e.layerX) / state.canvas.getZoom(),
- y: (e.pointer.y || e.e.layerY) / state.canvas.getZoom()
- }
- ]
- let polygon = new fabric.Polygon(polyPoint, {
- stroke: '#333333',
- strokeWidth: 1,
- fill: '#cccccc',
- opacity: 0.3,
- selectable: false,
- hasBorders: false,
- hasControls: false,
- evented: false,
- objectCaching: false
- })
- state.activeShape = polygon
- state.canvas.add(polygon)
- }
- state.activeLine = state.line
- state.pointArray.push(circle)
- state.lineArray.push(state.line)
- state.canvas.add(state.line)
- state.canvas.add(circle)
- }
- // 绘制不规则
- const generatePolygon = () => {
- // let points = clearPolygonLines()
- // let polygon = new fabric.Polygon(sortPoints(points), {
- // stroke: state.color,
- // strokeWidth: state.drawWidth,
- // fill: 'rgba(255, 255, 255, 0)',
- // opacity: 1,
- // hasBorders: false,
- // hasControls: false,
- // evented: false
- // })
- // state.canvas.add(polygon)
- let points = [{}]
- // console.log('state.pointArray', state.pointArray)
- for (let point in state.pointArray) {
- point = state.pointArray[point]
- // console.log(point.left, point.top)
- }
- state.pointArray.map(point => {
- points.push({
- x: point.left,
- y: point.top
- })
- state.canvas.remove(point)
- })
- state.lineArray.map(line => {
- state.canvas.remove(line)
- })
- state.canvas.remove(state.activeShape).remove(state.activeLine)
- let polygon = new fabric.Polygon(points, {
- stroke: state.color,
- strokeWidth: state.drawWidth,
- fill: 'rgba(255, 255, 255, 0)',
- opacity: 1,
- hasBorders: true,
- hasControls: false
- })
- state.canvas.add(polygon)
- resetPolygon()
- }
- // 坐标转换
- const transformMouse = (mouseX, mouseY) => {
- return { x: mouseX / 1, y: mouseY / 1 }
- }
- // 重置不规则四边形
- const resetPolygon = () => {
- state.activeLine = null
- state.activeShape = null
- state.polygonMode = false
- state.doDrawing = false
- state.drawType = null
- }
- // 清除绘制四边形的四个坐标点
- const clearPolygonLines = () => {
- let points = [{}]
- state.pointArray.forEach(point => {
- points.push({
- x: point.left,
- y: point.top
- })
- state.canvas.remove(point)
- })
- state.lineArray.forEach(line => {
- state.canvas.remove(line)
- })
- state.canvas.remove(state.activeShape).remove(state.activeLine)
- return points
- }
- // 撤销最后一次的操作
- const clearObjLast = () => {
- let canvasObjs = state.canvas.getObjects()
- let len = canvasObjs.length
- if (len > 1) {
- state.canvas.remove(canvasObjs[len - 1])
- }
- }
- // 全部清除
- const clearAll = () => {
- state.canvas.getObjects().forEach((element, index) => {
- if (index > 0) {
- state.canvas.remove(element)
- }
- })
- clearPolygonLines()
- resetPolygon()
- state.drawType = 'rectangle'
- }
- const getPoint = pi => {
- return Math.floor(pi / state.radio)
- }
- const getRealPoint = poi => {
- let dx = Math.abs(state.imgPoint.x > poi.x ? state.imgPoint.x - poi.x : state.imgPoint.x + poi.x) * state.realRadioX
- let dy = Math.abs(state.imgPoint.y > poi.y ? state.imgPoint.y - poi.y : state.imgPoint.y + poi.y) * state.realRadioY
- let rdx = Math.abs(state.realPoint.x - dx)
- let rdy = Math.abs(state.realPoint.y - dy)
- let minX = Math.min(Math.floor(rdx), props.width)
- let minY = Math.min(Math.floor(rdy), props.height)
- return { x: minX, y: minY }
- }
- // 生成真实分辨率图片的坐标点
- const getData = () => {
- let datas = [] as any
- let marks = ['tl', 'tr', 'br', 'bl']
- // if (state.lineArray.length > 0 && state.lineArray.length < 4) {
- // clearPolygonLines()
- // }
- datas.push(JSON.stringify(state.canvas.toJSON(['label'])))
- datas.push(state.canvas.toDataURL('image/png'))
- state.canvas.getObjects().forEach((item, index) => {
- // console.log(item, index)
- if (index > 0) {
- let aCoords = item.aCoords
- let point = {
- nodes: [],
- angle: item.angle,
- label: item.label
- }
- if (item.points) {
- item.points.forEach((item, idx) => {
- // if (aCoords[marks[idx]]) {
- // aCoords[marks[idx]].x = item.x
- // aCoords[marks[idx]].y = item.y
- // }
- // if (idx > 0) {
- point[idx] = getRealPoint({
- x: item?.x,
- y: item?.y
- })
- // }
- })
- } else {
- marks.forEach(mark => {
- let poi = {
- x: getPoint(aCoords[mark].x),
- y: getPoint(aCoords[mark].y)
- }
- // console.log(poi)
- poi = getRealPoint(poi)
- // console.log(poi)
- poi.x = poi.x / state.realRadioX / 1920
- poi.y = poi.y / state.realRadioY / 1080
- // console.log(poi)
- point['nodes'].push(poi)
- // point['nodes'].push(getRealPoint(poi))
- })
- }
- // if (item.points && item.points.length === 2) {
- // delete point['br']
- // delete point['bl']
- // }
- datas.push(point)
- // console.log(point)
- }
- })
- // console.log()
- return datas
- }
- // 获取归一化数据比例
- const normalization = () => {
- return {
- realRadioX: state.realRadioX,
- realRadioY: state.realRadioY
- }
- }
- defineExpose({ drawType: state.drawType, clearObjLast, clearAll, getData, normalization })
- onMounted(() => {
- loadInit()
- })
- </script>
- <style lang="scss" scoped>
- canvas {
- border: 1px dashed black;
- }
- .loading-box {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- width: 960px;
- height: 540px;
- font-size: 14px;
- color: #ea5413;
- }
- .draw-btn-group {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- width: 960px;
- margin-top: 10px;
- .active {
- .draw-rect {
- background: #ff00ff;
- border-color: #ff00ff;
- }
- }
- .shape-box {
- width: 120px;
- text-align: left;
- }
- .shape-border {
- display: block;
- width: 80px;
- height: 30px;
- margin-right: 30px;
- font-size: 12px;
- text-align: center;
- }
- .shape-border-ti {
- transform: skewX(-45deg);
- }
- .draw-icon {
- display: inline-block;
- width: 80px;
- height: 30px;
- }
- .draw-rect {
- width: 80px;
- border-color: #333333;
- border-style: solid;
- border-width: 1px;
- }
- .draw-line {
- position: relative;
- top: -14px;
- border-bottom: 2px solid #00ffff;
- }
- }
- </style>
|