1. 程式人生 > 其它 >基於前端le5le-topology寫一個自定義的元件(溫度計)

基於前端le5le-topology寫一個自定義的元件(溫度計)

技術標籤:canvasTopologyvueTs

自定義圖形在這裡插入圖片描述

這樣寫出來的自定義元件就是靈活的,可以自己隨意修改值。也可以通過後臺,動態改變。
自定義資料 name 對應值為自定義函式的名。

  {
    name: 'thermometer',
    icon: 't-icon t-rect',
    data: { 
      rect: {
        width: 60,
        height: 250,
      }, 
      name: 'thermometer',
      value:10,
      data: {
        thermometer:
{ Maximum:20,Minimum:-20,criticalValue:0,thresholdsColor:"#F40" }, }, }, },

TS 程式碼

declare const window: any;

程式碼入口
export function thermometer(ctx: CanvasRenderingContext2D, node: any) {
  const R = Math.floor(node.rect.width / 2);
  //獲取畫布節點的寬度。計算出大R。
  const r = Math.round((R *
1) / 2); ctx.fillStyle = node?.value > node?.data?.thermometer?.criticalValue ? node?.data?.thermometer?.thresholdsColor : node?.fillStyle ?? '#FF3C65'; //這裡是一個三元,和js2020 新語法。可以去了解一下 ctx.fill(); drawScale(ctx, node); ctx.clearRect(node?.rect.x + r, node?.rect.y, node?.rect?.width - R, getYByValue
(node,node?.value)); createdthermometer(ctx,node); } //畫骨架 function createdthermometer(ctx: CanvasRenderingContext2D, node: any){ const R = Math.floor(node.rect.width / 2) const r = Math.round((R * 1) / 2) ctx.beginPath(); ctx.lineWidth = node?.lineWidth; // 上半個圓形 ctx.arc(node.rect.x + R, node.rect.y + r, r, 0, Math.PI, true); // 下半個圓形 const theta = Math.acos((r * 1.0) / R); ctx.arc( node.rect.x + R, node.rect.y + node.rect.height - R, R, theta + Math.PI, -theta, true ); ctx.closePath(); ctx.stroke(); } function getYByValue(node:any,v:number) { const R = Math.floor(node.rect.width / 2); const r = Math.round((R * 1) / 2); const min = node?.data?.thermometer?.Minimum; const max = node?.data?.thermometer?.Maximum; // 刻度線總高度 const height = node.rect.height - 2 * R - 2 * r; // 起始刻度線所在位置 const zeroY = node.rect.height - 2 * R; //每條刻度線的距離。 const dy = height / (max - min); return zeroY - dy * v + dy * min; //返回當前值的刻度位置, (+ dy * min) 的意義是,假設min < 0 。要加上超出的位置的距離。 } // 畫刻度線 function drawScale(ctx: CanvasRenderingContext2D, node: any){ const R = Math.floor(node.rect.width / 2); const r = Math.round((R * 1) / 2); const min = node?.data?.thermometer?.Minimum; const max = node?.data?.thermometer?.Maximum; let x = node.rect.ex -r; let ey = node.rect.y; ctx.fillStyle = node.font.color ?? '#000'; for (let i = min; i <= max; i++) { // 刻度線 const y = getYByValue(node,i); ctx.beginPath(); ctx.moveTo(x, y + ey); if (i % 10 == 0) { ctx.lineWidth = 2; ctx.lineTo(x + r * 2 / 3, y + ey ); ctx.fillText(i as any, x + 15, y + 6 + ey); ctx.stroke(); } else { ctx.lineWidth = 1; if (i % 5 == 0) { ctx.lineTo(x + r / 2, y + ey ); } else { ctx.lineTo(x + r / 3, y + ey ); } } ctx.stroke(); } } //溫度計上的錨點 export function thermometerAnchors(node: any) { node.anchors.push(new window.topologyPoint(node.rect.x , node.rect.y + node.rect.height / 2, 4) ); node.anchors.push(new window.topologyPoint(node.rect.x + node.rect.width / 2, node.rect.y, 1)); node.anchors.push(new window.topologyPoint(node.rect.x + node.rect.width, node.rect.y + node.rect.height / 2, 2)); node.anchors.push(new window.topologyPoint(node.rect.x + node.rect.width / 2, node.rect.y + node.rect.height, 3)); }

註冊節點。

export function register() {
  window.registerTopologyNode('thermometer', thermometer, thermometerAnchors);  
}
 
  mounted() {
    register();
  }

寫的不好,可以去看官網文件,有詳解。