mirror of
https://github.com/ialley-workshop-open/uni-halo.git
synced 2026-06-11 12:49:30 +08:00
v1.0.0-beta 源码正式开源
This commit is contained in:
@@ -0,0 +1,449 @@
|
||||
<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>
|
||||
@@ -0,0 +1,787 @@
|
||||
<template>
|
||||
<view class="tm-render" @touchmove.stop.prevent="">
|
||||
|
||||
<!-- #ifdef MP-WEIXIN || MP-QQ || MP-KUAISHOU || MP-ALIPAY -->
|
||||
|
||||
<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 || MP-ALIPAY || APP-PLUS -->
|
||||
<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 -->
|
||||
|
||||
<!-- #ifdef APP-PLUS-->
|
||||
|
||||
<canvas
|
||||
@mouseup="CRender.touchend_app"
|
||||
@mousedown="CRender.touchstart_app"
|
||||
@mousemove="CRender.touchmove_app"
|
||||
@touchend="CRender.touchend_app"
|
||||
@touchmove="CRender.touchmove_app"
|
||||
@touchstart="CRender.touchstart_app"
|
||||
|
||||
:prop="app_opts" :change:prop="CRender.update_app_opts" :style="{width:`${c_w}px`,height:`${c_h}px`}" id="exid" canvas-id="exid" ></canvas>
|
||||
|
||||
<!-- #endif -->
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifndef APP-PLUS
|
||||
import CRender from '@/tm-vuetify/tool/function/crender/class/crender.class'
|
||||
// #endif
|
||||
|
||||
|
||||
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,
|
||||
|
||||
app_opts:{
|
||||
render_app:null,
|
||||
graph:null,
|
||||
fun:[],
|
||||
canvaConfig:null
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(async function() {
|
||||
// #ifndef APP-PLUS
|
||||
this.inits();
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
let res = await this.$Querey('.tm-render', this).catch(e => {})
|
||||
let p = res[0];
|
||||
this.$set(this.app_opts,'canvaConfig',p)
|
||||
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
|
||||
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);
|
||||
// 12296升级改造
|
||||
t.$emit('render', render.area);
|
||||
})
|
||||
|
||||
}).exec()
|
||||
|
||||
//#endif
|
||||
//#ifndef MP-WEIXIN || MP-QQ || MP-KUAISHOU || MP-ALIPAY || APP-PLUS
|
||||
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() {
|
||||
// 12296升级改造
|
||||
t.$emit('render', render.area);
|
||||
// t.$emit('render', render.area);
|
||||
})
|
||||
|
||||
//#endif
|
||||
},
|
||||
wait(time) {
|
||||
return new Promise(resolve => setTimeout(resolve, time))
|
||||
},
|
||||
getTextWidthAndPos(shape) {
|
||||
// #ifdef APP-PLUS
|
||||
return [0,0,0,0];
|
||||
// #endif
|
||||
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() {
|
||||
// #ifdef APP-PLUS
|
||||
return this.app_opts.render_app;
|
||||
// #endif
|
||||
return render;
|
||||
},
|
||||
renderCavans(e){
|
||||
render = e;
|
||||
//app触发这里。
|
||||
this.$emit('render', render.area);
|
||||
|
||||
},
|
||||
//app-plus代理执行函数,参数一为函数名称,参数二为参数。
|
||||
appCallFun(funName,arg){
|
||||
// #ifdef APP-PLUS
|
||||
this.$set( this.app_opts,'fun',[funName,arg])
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
console.error("此函数为APP-PLUS专用,详见:https://jx2d.cn/guid/render/%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8.html")
|
||||
// #endif
|
||||
},
|
||||
async addGraph(obj) {
|
||||
let t = this;
|
||||
let pf = obj;
|
||||
// #ifdef APP-PLUS
|
||||
this.$set( this.app_opts,'graph',obj)
|
||||
return
|
||||
// #endif
|
||||
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) => {
|
||||
// 要判断谁的层级高就是先托动谁。
|
||||
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
|
||||
});
|
||||
} else {
|
||||
this.dragGrpahId = ""
|
||||
}
|
||||
|
||||
this.$emit('touchstart', {
|
||||
x: x,
|
||||
y: y
|
||||
})
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
<script module="CRender" lang="renderjs">
|
||||
|
||||
var cdr = require('@/tm-vuetify/tool/function/crender/crender.min.js')
|
||||
const CRender = window.CRender.CRender
|
||||
var render_app;
|
||||
export default {
|
||||
mounted() {
|
||||
// #ifdef APP-PLUS
|
||||
this.$nextTick(function(){
|
||||
this.initsAppH5();
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
initsAppH5(e) {
|
||||
let t = this;
|
||||
let canvas = document.querySelector('#exid').querySelector('canvas')
|
||||
let canvasPrent = document.querySelector('.tm-render')
|
||||
let w = canvasPrent.offsetWidth;
|
||||
let h = canvasPrent.offsetHeight;
|
||||
canvas.style.width = w+'px';
|
||||
canvas.style.height = h+'px';
|
||||
render_app = new CRender(canvas)
|
||||
|
||||
this.$ownerInstance.$vm.$set(this.$ownerInstance.$vm.app_opts,'render_app',render_app)
|
||||
setTimeout(function() {
|
||||
t.$ownerInstance.callMethod('renderCavans', render_app)
|
||||
}, 10);
|
||||
|
||||
},
|
||||
update_app_opts(newValue, oldValue, ownerInstance, instance) {
|
||||
if(newValue.graph){
|
||||
let graph = render_app.add(newValue.graph)
|
||||
this.$ownerInstance.$vm.app_opts.graph=null;
|
||||
}
|
||||
if(newValue.fun){
|
||||
if(typeof(newValue.fun)=="object" && Array.isArray(newValue.fun)){
|
||||
if(newValue.fun.length>0){
|
||||
if(newValue.fun.length==1){
|
||||
render_app[newValue.fun[0]]();
|
||||
}else if(newValue.fun.length==2){
|
||||
render_app[newValue.fun[0]](newValue.fun[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
wait(time) {
|
||||
return new Promise(resolve => setTimeout(resolve, time))
|
||||
},
|
||||
getTextWidthAndPos(shape) {
|
||||
// #ifdef APP-PLUS
|
||||
return [0,0,0,0];
|
||||
// #endif
|
||||
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
|
||||
},
|
||||
touchend_app(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.app_opts.canvaConfig.left
|
||||
evy = event.pageY - this.app_opts.canvaConfig.top;
|
||||
|
||||
}
|
||||
|
||||
let x = evx;
|
||||
let y = evy;
|
||||
|
||||
|
||||
this.dragGrpahId = "";
|
||||
this.isDrag = false
|
||||
//触发画板的事件。
|
||||
this.$emit('touchend', {
|
||||
x: x,
|
||||
y: y
|
||||
})
|
||||
//在那个元素上离开的。
|
||||
let gps = render_app.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_app(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.app_opts.canvaConfig.left
|
||||
evy = event.pageY - this.app_opts.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_app.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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
touchstart_app(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.app_opts.canvaConfig.left
|
||||
evy = event.pageY - this.app_opts.canvaConfig.top
|
||||
isPc = true;
|
||||
}
|
||||
|
||||
let x = evx
|
||||
let y = evy
|
||||
|
||||
let gps = render_app.graphs;
|
||||
|
||||
//点中了哪些图片,第一个是最顶层的,依次类推。
|
||||
let isClickGrpahs = gps.filter((el, index) => {
|
||||
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
|
||||
});
|
||||
} else {
|
||||
this.dragGrpahId = ""
|
||||
}
|
||||
|
||||
this.$emit('touchstart', {
|
||||
x: x,
|
||||
y: y
|
||||
})
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
body {}
|
||||
</style>
|
||||
Reference in New Issue
Block a user