SocialNetworks_duan/src/utils/customePaint.js
2025-08-12 10:23:07 +08:00

165 lines
5.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//自定义绘制节点的方法
export const paintNodeFunction = (storeId) => {
return function (ctx, onlyShape) {
//默认绘制数据类型图片
if (this.properties.typeIcon) {
if (this.selected || this.showSelected) {
this.drawShape(ctx, onlyShape)
}
if (this.alpha < 1) {
ctx.save()
ctx.globalAlpha = this.alpha
ctx.drawImage(
this.properties.typeIcon,
-this.width / 2,
-this.height / 2,
this.width,
this.height
)
ctx.restore()
} else {
ctx.drawImage(
this.properties.typeIcon,
-this.width / 2,
-this.height / 2,
this.width,
this.height
)
}
} else {
this.drawShape(ctx, onlyShape)
}
if (storeId == "anomalousGroup") {
// 半径 & 样式参数(按需调整)
// ===== 三层:实心圆 + 半透明边框 + 外圈虚线 =====
const rFill = this.radius // 实心圆半径
const ringWidth = 15 // 半透明边框的宽度
const ringGap = 0 // 实心与半透明边框之间的间隙(需要留缝就调大)
const outerGap = 0 // 半透明边框与虚线之间的间隙
const dashWidth = 2 // 虚线线宽
const dash = 2,
gap = 4 // 虚线样式
const ringAlphaFactor = 0.5 // 半透明边框的相对透明度(相对于 this.alpha
// 1) 中间实心圆(填充)
ctx.save()
ctx.beginPath()
ctx.arc(0, 0, rFill, 0, Math.PI * 2)
ctx.fillStyle = `rgba(${this.fillColor}, ${this.alpha})`
ctx.fill()
ctx.restore()
// 2) 同色半透明边框(描边,不是挖空)
const rRing = rFill + ringGap + ringWidth / 2
ctx.save();
const rInner = rFill + ringGap;
const rOuter = rInner + ringWidth;
// 一个小工具函数,复用甜甜圈路径
const ringPath = () => {
ctx.beginPath();
ctx.arc(0, 0, rOuter, 0, Math.PI * 2, false);
ctx.arc(0, 0, rInner, 0, Math.PI * 2, true);
};
// 选择配色方案
const fc = (this.fillColor || "").replace(/\s+/g, "");
const isMint = fc === "75,241,184";
const isBlue = fc === "69,192,242";
const isRed = fc === "255,50,60";
const isYellow = fc === "250,222,37";
// 默认都按照 SVG每层 0.24 透明度(再乘整体 alpha
const layerAlpha = 0.24 * (this.alpha ?? 1);
// --- 第 2-1 层:线性渐变 (#0FE9BE -> #91FFB2), fill-opacity=0.24 ---
ringPath();
let lg = ctx.createLinearGradient(-rOuter, 0, rOuter, 0);
if(isMint){
lg.addColorStop(0, '#0FE9BE');
lg.addColorStop(1, '#91FFB2');
}else if(isBlue){
lg.addColorStop(0, "#009DFF");
lg.addColorStop(1, "#00FFF2");
}else if(isRed){
lg.addColorStop(0, '#FF0000');
lg.addColorStop(1, '#FF0909');
}else if(isYellow){
lg.addColorStop(0, '#FFDA09');
lg.addColorStop(1, '#FFDA09');
}
ctx.globalAlpha = 0.24 * (this.alpha ?? 1); // 与节点整体透明度相乘
ctx.fillStyle = lg;
ctx.fill();
// --- 第 2-2 层:径向渐变 (E6F9FF -> BEFFDB(0.5) -> 透明), fill-opacity=0.24 ---
// 参照 SVG 的 gradientTransform(translate(35.15,12.16) 相对圆心(20,16)):
// 约等于中心点在右上方 (≈ 0.95R, -0.24R)半径≈1.52R
ringPath();
const cx = 0.95 * rOuter;
const cy = -0.24 * rOuter;
let rg = ctx.createRadialGradient(cx, cy, 0, cx, cy, 1.52 * rOuter);
if(isMint){
rg.addColorStop(0.0, 'rgba(230,249,255,1)'); // #E6F9FF
rg.addColorStop(0.3693,'rgba(190,255,219,0.5)'); // #BEFFDB @ 0.5
rg.addColorStop(1.0, 'rgba(0,0,0,0)');
}else if(isBlue){
rg.addColorStop(0.0, 'rgba(229,249,255,1)');
rg.addColorStop(0.3693,'rgba(141,255,253,0.5)');
rg.addColorStop(1.0, 'rgba(0, 0, 0, 0)');
}else if(isRed){
rg.addColorStop(0.0, 'rgba(255,255,255,1)');
rg.addColorStop(0.3693,'rgba(255,200,200,0.5)');
rg.addColorStop(1.0, 'rgba(0, 0, 0, 0)');
}else if(isYellow){
rg.addColorStop(0.0, 'rgba(229,249,255,1)');
rg.addColorStop(0.3693,'rgba(254,255,200,0.5)');
rg.addColorStop(1.0, 'rgba(0, 0, 0, 0)');
}
ctx.globalAlpha = 0.24 * (this.alpha ?? 1);
ctx.fillStyle = rg;
ctx.fill();
ctx.restore();
// 3) 外圈虚线(同色)
ctx.save()
ctx.beginPath()
const rDash = rRing + ringWidth / 2 + outerGap + dashWidth / 2
ctx.arc(0, 0, rDash, 0, Math.PI * 2)
ctx.lineWidth = dashWidth
ctx.setLineDash([dash, gap])
ctx.lineCap = "round"
ctx.strokeStyle = `rgba(${this.fillColor}, ${this.alpha})`
ctx.stroke()
ctx.setLineDash([]) // 清理,避免影响后续绘制
ctx.restore()
} else {
ctx.beginPath()
ctx.arc(0, 0, this.radius + 6, 0, Math.PI * 2)
ctx.lineWidth = 5
ctx.strokeStyle = `rgba(${this.fillColor},${this.alpha * 0.4})`
ctx.stroke()
}
this.paintText(ctx) //调用内部方法绘制文字
}
}
//自定义连线的方法
export const paintLineFunction = function (ctx, needHideText) {
this.drawOriginalLine(ctx, needHideText) //内置默认的绘制方法
//指定路径,用于鼠标检测选中
this.path = [
{ x: this.source.cx, y: this.source.cy },
{ x: this.target.cx, y: this.target.cy }
]
// //绘制路径
ctx.beginPath()
ctx.moveTo(this.source.cx, this.source.cy)
ctx.lineTo(this.target.cx, this.target.cy)
this.setLineStyle(ctx)
ctx.stroke()
// //绘制连线上文字(内部方法)
this.paintTextOnLineWithAngle(ctx, this.source, this.target)
}