You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

450 lines
11 KiB
Vue

<template>
<view class="tm-render" @touchmove.stop.prevent="">
<!-- #ifdef MP-WEIXIN || MP-QQ || MP-KUAISHOU -->
<canvas :style="{width:`${c_w}px`,height:`${c_h}px`}" @mouseup="touchend" @mousedown="touchstart"
@mousemove="touchmove" @touchend="touchend" @touchmove="touchmove" @touchstart="touchstart" id="exid"
canvas-id="exid" type="2d"></canvas>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN || MP-QQ || MP-KUAISHOU -->
<canvas :style="{width:`${c_w}px`,height:`${c_h}px`}" @mouseup="touchend" @mousedown="touchstart"
@mousemove="touchmove" @touchend="touchend" @touchmove="touchmove" @touchstart="touchstart" id="exid"
canvas-id="exid" ></canvas>
<!-- #endif -->
</view>
</template>
<script>
import CRender from '@/tm-vuetify/tool/function/crender/class/crender.class'
// import Graph from '@/tm-vuetify/tool/function/crender/class/graph.class'
// import {CRender,GRAPHS} from '@/tm-vuetify/tool/function/render/index.js'
let render = null;
export default {
name: "tm-render",
props: {
width: {
type: Number,
default: 0
},
height: {
type: Number,
default: 600
}
},
computed: {
c_w: {
get: function() {
return this.cavan_width;
},
set: function(val) {
this.cavan_width = val;
},
},
c_h: function() {
return uni.upx2px(this.height);
}
},
created() {
const dpr = uni.getSystemInfoSync().pixelRatio
this.dpr = dpr;
this.c_w = uni.upx2px(this.width);
},
data() {
return {
cavan_width: 0,
canvaConfig: null,
dragGrpahId: '',//当前正在拖动或者点击的项目id.
old_x: 0,
old_y: 0,
isDrag: false,
dpr: 1
};
},
mounted() {
this.$nextTick(function() {
this.inits();
})
},
destroyed() {
render = null;
clearTimeout(555)
},
methods: {
async inits() {
let t = this;
let res = await this.$Querey('.tm-render', this).catch(e => {})
let p = res[0];
t.c_w = p.width || 300;
t.canvaConfig = p;
//#ifdef MP-WEIXIN || MP-QQ || MP-KUAISHOU
uni.createSelectorQuery().in(t).select('#exid').fields({
node: true,
context: true,
}, function(res) {
let canvas = res.node;
let ctx = canvas.getContext('2d')
ctx['dpr'] = t.dpr;
ctx['scaledpr'] = 10 / (10 * t.dpr);
const w = ctx['width'] = t.c_w
const h = ctx['height'] = t.c_h
// canvas.width = res[0].width * dpr
// canvas.height = res[0].height * dpr
const dpr = uni.getSystemInfoSync().pixelRatio
canvas.width = w * dpr
canvas.height = h * dpr
// 设置 canvas 坐标原点
ctx.translate(0, 0);
ctx.scale(dpr, dpr)
render = new CRender(ctx, t, canvas)
t.$nextTick(function() {
t.$emit('render', render.area);
})
}).exec()
//#endif
//#ifndef MP-WEIXIN || MP-QQ || MP-KUAISHOU
let ctx = uni.createCanvasContext('exid', t)
ctx['dpr'] = t.dpr;
ctx['scaledpr'] = 10 / (10 * t.dpr);
const w = ctx['width'] = t.c_w
const h = ctx['height'] = t.c_h
render = new CRender(ctx, t)
t.$nextTick(function() {
t.$emit('render', render.area);
})
//#endif
},
wait(time) {
return new Promise(resolve => setTimeout(resolve, time))
},
getTextWidthAndPos(shape) {
if (!render) return [0, 0, 0, 0];
let {
content,
position,
maxWidth,
rowGap
} = shape.shape
const {
textBaseline,
fontSize,
textAlign
} = shape.style
let [x, y] = position
content = content.split('\n')
const rowNum = content.length
const lineHeight = fontSize + rowGap
const allHeight = rowNum * lineHeight - rowGap
const twidth = render.ctx.measureText(content + "").width;
if (textBaseline === 'middle') {
y -= allHeight * rowNum + fontSize / 2
}
if (textBaseline === 'bottom') {
y += fontSize
}
if (textAlign === 'center') {
x -= twidth / 2
y += fontSize
}
return [x, y, twidth, allHeight]
// measureText
},
getRender() {
return render;
},
async addGraph(obj) {
let t = this;
let pf = obj;
if (typeof obj == 'object' && Array.isArray(obj)) {
let c = obj.filter(el => {
return {
...el,
tmid: uni.$tm.guid()
};
})
pf = c;
} else if (typeof obj == 'object' && !Array.isArray(obj)) {
pf = [{
...pf,
tmid: uni.$tm.guid()
}]
}
let graphs = pf.map(config => render.add(config))
graphs.forEach((graph, i) => {
const config = pf[i]
t.updateGraphConfigByKey(graph, config)
})
await render.launchAnimation()
//释放内存。
// graphs = []
return graphs.length == 1 ? graphs[0] : graphs;
},
//添加完毕需要更新下,才会显示。
updateGraphConfigByKey(graph, config) {
const keys = Object.keys(config)
keys.forEach(async key => {
if (key === 'shape' || key === 'style') {
// graph.animation('shape', {x:config.shape.x+5}, true)
await graph.animation(key, config[key], true)
} else {
graph[key] = config[key]
}
})
},
touchend(event) {
let t = this;
let evx = 0;
let evy = 0;
//触摸
if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
evx = event.changedTouches[0].x
evy = event.changedTouches[0].y
//电脑端。
} else {
evx = event.pageX - this.canvaConfig.left
evy = event.pageY - this.canvaConfig.top;
}
let x = evx;
let y = evy;
this.dragGrpahId = "";
this.isDrag = false
//触发画板的事件。
this.$emit('touchend', {
x: x,
y: y
})
//在那个元素上离开的。
let gps = render.graphs;
let isClickGrpahs = gps.filter((el, index) => {
if (el.name == 'text') {
let rect = t.getTextWidthAndPos(el);
el.hoverRect = rect
}
return el.hoverCheck([x, y], el) || el.hoverCheckProcessor([x, y], el);
});
if (isClickGrpahs.length > 0) {
let nowgap = isClickGrpahs[0];
// 执行元素上绑定的事件。
if (nowgap[event.type]) nowgap[event.type].call(nowgap, {
x: x,
y: y
});
}
},
touchmove(event) {
let t = this;
let evx = 0;
let evy = 0;
let isPc = false
//触摸
if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
evx = event.changedTouches[0].x
evy = event.changedTouches[0].y
isPc = false
//电脑端。
} else {
evx = event.pageX - this.canvaConfig.left
evy = event.pageY - this.canvaConfig.top;
isPc = true;
}
let movex = evx - this.old_x;
let movey = evy - this.old_y;
let x = evx;
let y = evy;
// 触发发画板的事件
this.$emit('touchmove', {
x: x,
y: y
})
if(this.isDrag==false) return;
//在哪个元素移动的。
let gps = render.graphs;
let isClickGrpahs = gps.filter((el, index) => {
return (el.hoverCheck([x, y], el) || el.hoverCheckProcessor([x, y], el))&&el.tmid==t.dragGrpahId;
});
if (isClickGrpahs.length > 0) {
let nowgap = isClickGrpahs[0];
if (isPc) {
movex = evx - this.old_x;
movey = evy - this.old_y;
}
if ((nowgap.drag === true && this.isDrag == true) || (nowgap.drag === true && isPc == false)) {
if (nowgap.name == "circle" || nowgap.name == "ellipse" ||
nowgap.name == "ring" || nowgap.name == "arc" || nowgap.name == "regPolygon") {
nowgap.attr('shape', {
rx: movex,
ry: movey
})
} else if (nowgap.name == "rect" ||nowgap.name == 'rectRound'|| nowgap.name == "path"|| nowgap.name == "image"|| nowgap.name == "star" || nowgap.name =='arrow') {
nowgap.attr('shape', {
x: movex,
y: movey
})
} else if (nowgap.name == "text") {
nowgap.attr('shape', {
position: [movex, movey]
})
}
// 执行元素上绑定的事件。
if (nowgap[event.type]) nowgap[event.type].call(nowgap, {
x: movex,
y: movey
});
// if(nowgap['mousemove']||nowgap['touchmove']){
// if (nowgap['mousemove']) nowgap.mousemove.call(nowgap,{x:movex,y:movey})
// if (nowgap['touchmove']) nowgap.touchmove.call(nowgap,{x:movex,y:movey})
// }
}
//配置不允许拖出边界。
// if(this.dragGrpahId === nowgap.tmid
// && movex+nowgap.shape.w<this.canvaConfig.width
// && movey+nowgap.shape.h<this.canvaConfig.height
// && x>=0&&y>=0&&movex>=0&&movey>=0
// ){
// }
// this.$emit('shape:touchmove',{x:x,y:y,shape:nowgap})
}
},
touchstart(event) {
let t = this;
let evx = 0;
let evy = 0;
let isPc = false
//触摸
if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
evx = event.changedTouches[0].x
evy = event.changedTouches[0].y
isPc = false
//电脑端。
} else {
evx = event.pageX - this.canvaConfig.left
evy = event.pageY - this.canvaConfig.top
isPc = true;
}
let x = evx
let y = evy
let gps = render.graphs;
//点中了哪些图片,第一个是最顶层的,依次类推。
let isClickGrpahs = gps.filter((el, index) => {
// if (el.name == 'text') {
// let rect = t.getTextWidthAndPos(el);
// el.hoverRect = rect
// }
// 要判断谁的层级高就是先托动谁。
return el.hoverCheck([x, y], el) || el.hoverCheckProcessor([x, y], el);
});
if (isClickGrpahs.length > 0) {
var indexOfMax = 0;
var max = isClickGrpahs.reduce( (a,c,i) => c.index > a ? (indexOfMax = i,c.index) : a, 0)
let nowgap = isClickGrpahs[indexOfMax];
if (nowgap.drag === true) {
this.dragGrpahId = nowgap.tmid;
let gapPos = [];
if (nowgap.name == "circle" || nowgap.name == "ellipse" ||
nowgap.name == "ring" || nowgap.name == "arc" || nowgap.name == "regPolygon"
) {
gapPos = [nowgap.shape.rx, nowgap.shape.ry]
} else if (nowgap.name == "rect" ||nowgap.name == 'rectRound'|| nowgap.name == "path"|| nowgap.name == "image"|| nowgap.name == "star"|| nowgap.name =='arrow') {
gapPos = [nowgap.shape.x, nowgap.shape.y]
} else if (nowgap.name == "text") {
gapPos = nowgap.shape.position
}
if (isPc) {
this.old_x = evx - gapPos[0]
this.old_y = evy - gapPos[1];
} else {
this.old_x = x - gapPos[0];
this.old_y = y - gapPos[1];
}
this.isDrag = true
}
// 执行元素上绑定的事件。
if (nowgap[event.type]) nowgap[event.type].call(nowgap, {
x: x,
y: y
});
// if(nowgap['mousedwon']||nowgap['touchstart']||nowgap['mouseenter']){
// if (nowgap['mousedwon']) nowgap.mousedwon.call(nowgap,{x:x,y:y})
// if (nowgap['touchstart']) nowgap.touchstart.call(nowgap,{x:x,y:y})
// if (nowgap['mouseenter']) nowgap.mouseenter.call(nowgap,{x:x,y:y})
// }
} else {
this.dragGrpahId = ""
}
this.$emit('touchstart', {
x: x,
y: y
})
},
},
}
</script>
<style lang="scss">
body {}
</style>