123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787 |
- <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>
|