2 lines
3.2 KiB
JavaScript
2 lines
3.2 KiB
JavaScript
"use strict";const t=require("./common/vendor.js"),e={name:"WordCloud",props:{wordData:{type:Array,required:!0,default:()=>[]},width:{type:Number,default:300},height:{type:Number,default:300},colorList:{type:Array,default:()=>["#60A5FA","#FEC200","#EF4444"]},fontSizeConfig:{type:Object,default:()=>({minSize:12,maxSize:40,scaleFactor:.1})}},data(){return{canvasWidth:this.width,canvasHeight:this.height,ctx:null,placedWords:[]}},watch:{wordData:{handler(){this.drawWordCloud()},deep:!0}},mounted(){this.initCanvas()},methods:{async initCanvas(){await new Promise((t=>setTimeout(t,50)));t.index.createSelectorQuery().in(this).select(".word-cloud-canvas").fields({node:!0,size:!0}).exec((async e=>{if(!e||!e[0]||!e[0].node)return void console.error("获取canvas节点失败,请检查canvas是否正确渲染");const a=e[0].node;let i=null;try{i=a.getContext("2d")}catch(o){console.warn("获取2d上下文失败,尝试兼容处理",o),i=t.index.createCanvasContext("wordCloudCanvas",this)}if(!i)return void console.error("无法获取canvas 2d上下文");const s=t.index.getSystemInfoSync().pixelRatio||1;a.width=this.canvasWidth*s,a.height=this.canvasHeight*s,i.scale(s,s),this.ctx=i,this.drawWordCloud()}))},drawWordCloud(){if(!this.ctx||!this.wordData.length)return;this.ctx.clearRect(0,0,this.canvasWidth,this.canvasHeight),this.placedWords=[];const t=[...this.wordData].sort(((t,e)=>e.value-t.value)),e=t.map((t=>t.value));this.valueMax=Math.max(...e),this.valueMin=Math.min(...e),t.forEach(((t,e)=>{this.placeWord(t,e)}))},placeWord(t,e){const a=this.ctx,{minSize:i,maxSize:s,scaleFactor:o}=this.fontSizeConfig;let n=1;this.valueMax!==this.valueMin&&(n=(t.value-this.valueMin)/(this.valueMax-this.valueMin));const h=Math.min(i+(s-i)*n*o,s),r=120*(Math.random()-.5)*Math.PI/180;a.font=`${h}px sans-serif`;const c=a.measureText(t.text||t.name).width,d=1.05*h;for(let l=0;l<150;l++){const e=.05*this.canvasWidth+Math.random()*this.canvasWidth*.9,i=.05*this.canvasHeight+Math.random()*this.canvasHeight*.9;if(!this.checkOverlap(e,i,c,d,r,2)){const s=this.canvasWidth/2,o=this.canvasHeight/2,n=Math.sqrt(Math.pow(e-s,2)+Math.pow(i-o,2)),l=Math.sqrt(Math.pow(s,2)+Math.pow(o,2));let u;u=n>.66*l?this.colorList[0]:n>.33*l?this.colorList[1]:this.colorList[2],a.fillStyle=u,this.drawTextAtPosition(t.text||t.name,e,i,r,h),this.placedWords.push({x:e,y:i,width:c,height:d,angle:r});break}}},checkOverlap(t,e,a,i,s,o=2){const n=this.getBoundingRect(t,e,a,i,s,o);for(const h of this.placedWords){const t=this.getBoundingRect(h.x,h.y,h.width,h.height,h.angle,o);if(n.left<t.right&&n.right>t.left&&n.top<t.bottom&&n.bottom>t.top)return!0}return!1},getBoundingRect(t,e,a,i,s,o=2){const n=Math.cos(s),h=Math.sin(s),r=(a-o)/2,c=(i-o)/2,d=[{x:-r,y:-c},{x:-r,y:c},{x:r,y:c},{x:r,y:-c}].map((a=>({x:t+a.x*n-a.y*h,y:e+a.x*h+a.y*n})));return{left:Math.min(...d.map((t=>t.x))),right:Math.max(...d.map((t=>t.x))),top:Math.min(...d.map((t=>t.y))),bottom:Math.max(...d.map((t=>t.y)))}},drawTextAtPosition(t,e,a,i,s){const o=this.ctx;o.save(),o.translate(e,a),o.rotate(i),o.textAlign="center",o.textBaseline="middle",o.fillText(t,0,0),o.restore()}}};const a=t._export_sfc(e,[["render",function(t,e,a,i,s,o){return{a:s.canvasWidth+"px",b:s.canvasHeight+"px"}}],["__scopeId","data-v-e748f4a2"]]);exports.MiniProgramPage=a;
|