|
|
const e="e74e3f4e-d737-4440-88ca-b1adaaa97d4d",n="custom-progress-guage",t="进度仪表图",a='<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1695784641645" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6357" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 260.266667l42.666667 262.4c0 21.333333-19.2 36.266667-42.666667 36.266666s-42.666667-17.066667-42.666667-36.266666" fill="#4C64FE" p-id="6358"></path><path d="M488.533333 85.333333C264.533333 98.133333 85.333333 285.866667 85.333333 509.866667c0 155.733333 81.066667 290.133333 204.8 364.8 23.466667 14.933333 51.2-2.133333 51.2-29.866667V832c0-14.933333-6.4-29.866667-19.2-38.4-34.133333-23.466667-64-51.2-87.466666-85.333333 23.466667-8.533333 36.266667-34.133333 27.733333-57.6-8.533333-25.6-34.133333-38.4-59.733333-32l-12.8 6.4c-14.933333-40.533333-21.333333-85.333333-19.2-132.266667 2.133333-32 8.533333-64 19.2-91.733333 10.666667 8.533333 27.733333 10.666667 42.666666 6.4 25.6-8.533333 38.4-34.133333 32-59.733334-4.266667-14.933333-17.066667-25.6-29.866666-29.866666 53.333333-76.8 136.533333-130.133333 232.533333-142.933334 0 4.266667 0 8.533333 2.133333 12.8 8.533333 25.6 34.133333 38.4 59.733334 32 19.2-6.4 32-23.466667 34.133333-44.8 98.133333 12.8 183.466667 70.4 236.8 149.333334-14.933333 12.8-23.466667 32-17.066667 51.2 8.533333 23.466667 32 38.4 57.6 32 10.666667 32 17.066667 68.266667 17.066667 104.533333 0 40.533333-6.4 76.8-19.2 113.066667-10.666667-6.4-25.6-10.666667-40.533333-6.4-25.6 8.533333-38.4 34.133333-32 59.733333 4.266667 14.933333 14.933333 23.466667 27.733333 29.866667-23.466667 34.133333-55.466667 64-89.6 87.466666-12.8 8.533333-19.2 21.333333-19.2 36.266667v12.8c0 27.733333 29.866667 44.8 55.466667 29.866667 121.6-74.666667 200.533333-209.066667 200.533333-362.666667C938.666667 268.8 733.866667 72.533333 488.533333 85.333333z" fill="#4C64FE" opacity=".6" p-id="6359"></path><path d="M661.333333 142.933333c0-19.2-12.8-36.266667-29.866666-40.533333-44.8-12.8-93.866667-19.2-142.933334-17.066667C264.533333 98.133333 85.333333 285.866667 85.333333 509.866667c0 155.733333 81.066667 290.133333 204.8 364.8 23.466667 14.933333 51.2-2.133333 51.2-29.866667V832c0-14.933333-6.4-29.866667-19.2-38.4-34.133333-23.466667-64-51.2-87.466666-85.333333-34.133333-40.533333-44.8-83.2-44.8-83.2-14.933333-40.533333-21.333333-85.333333-19.2-132.266667 2.133333-32 8.533333-64 19.2-91.733333 0 0 8.533333-40.533333 44.8-83.2 53.333333-76.8 136.533333-130.133333 232.533333-142.933334 0 0 49.066667-10.666667 96 0 14.933333 2.133333 29.866667 4.266667 44.8 8.533334 27.733333 8.533333 53.333333-10.666667 53.333333-40.533334z" fill="#4C64FE" p-id="6360"></path></svg>',i="svg",l="动态",o="图表组件",u=!1,c=!0,d="时间",s=`{"type":"page","id":"u:270584784ce1","name":"page1","asideResizor":false,"style":{"boxShadow":" 0px 0px 0px 0px transparent"},"pullRefresh":{"disabled":true},"body":[{"type":"tabs","name":"tab","tabs":[{"title":"样式","icon":"fa fa-th-large","body":[{"type":"form","title":"","name":"basicPropForm","body":[{"type":"input-text","label":"名称","name":"nodeAlias","id":"u:6b126f0520cb","size":"full","mode":"horizontal","inputControlClassName":"w-100","className":"m-b"},{"type":"input-text","label":"ID ","name":"id","id":"u:6232710ac003","size":"full","mode":"horizontal","inputControlClassName":"w-100","className":"m-b"},{"type":"grid","id":"u:c605398a724c","className":"m-b","columns":[{"body":[{"type":"input-number","label":"宽度","name":"width","keyboard":true,"id":"u:dcc0c21d16f6","step":1,"suffix":"px","placeholder":"组件左边距","size":"full","mode":"horizontal","className":"m-b","value":200,"labelAlign":"left","precision":2,"inputClassName":"w-full","labelClassName":"w-8"}],"id":"u:14cc19d6ffb0","md":6},{"body":[{"type":"input-number","label":"高度","name":"height","keyboard":true,"id":"u:cd6fdff9ca88","step":1,"suffix":"px","placeholder":"组件
"nodes": [ { "id": "2d10edaf-edb8-40ef-927b-bf4fee5718a4", "type": "custom-progress-guage", "x": 200, "y": 200, "text": { "value": "", "x": 200, "y": 200 }, "properties": { "id": "2d10edaf-edb8-40ef-927b-bf4fee5718a4", "width": 200, "height": 200, "x": 200, "y": 200, "rotation": 0, "opacity": 1, "grid": { "show": false }, "range": { "endAngle": -270, "startAngle": 90, "min": 0, "splitNumber": 12, "max": 240, "warnValue": 1000 }, "pointer": { "show": false, "itemStyle": { "color": "#b8e986" } }, "axisLine": { "show": false, "roundCap": false, "lineStyle": { "color": [ { "ratio": "0", "color": "#00FFFF" }, { "ratio": "1", "color": "rgba(80, 227, 194, 1)" } ], "width": 2 } }, "axisTick": { "show": false }, "splitLine": { "show": true, "length": 12, "lineStyle": { "color": "rgba(80, 227, 194, 1)", "width": 1 }, "distance": 0 }, "axisLabel": { "show": false }, "title": { "show": true, "color": "" }, "nextNewLine": false, "innerCircleLine": { "show": false, "color": "#0CD3DB", "backColor": "rgba(0,255,255,0.05)" }, "innerCircle": { "show": true, "borderColor": "rgba(80, 227, 194, 1)", "backColor": "rgba(0,255,255,0.05)" }, "outerCircleLine": { "show": true, "color": "rgba(80, 227, 194, 1)" }, "codeConfig": "return option", "progress": { "show": false, "roundCap": false }, "nodeAlias": "进度仪表图", "showDefaultValue": false, "showUnit": false, "fontSize": 0, "itemStyle": { "color": "rgba(80, 227, 194, 1)" }, "unit": { "fontSize": 12, "color": "rgba(80, 227, 194, 1)" }, "valueConfig": { "color": "rgba(80, 227, 194, 1)", "fontSize": 14 }, "dynamic": { "normalData": { "dataPoint": "", "compareType": "", "conditionVariables": [], "defaultValue": "", "unit": "" } } } } ]}`,javascript:`const { createApp, createVNode, render } = Vue;const app = createApp({})
const defaultVal = 50
// 获取圆上面某点的坐标(x0, y0表示坐标,r半径,angle角度)
function getCirlPoint(x0, y0, r, angle) { let x1 = x0 + r * Math.cos(angle * Math.PI / 180) let y1 = y0 + r * Math.sin(angle * Math.PI / 180) return { x: x1, y: y1 }}
const ProgressGauge = { template: '<div :id="chartId" :style="getStyle"></div>', props: { chartId: { type: String, default: '' }, currentData: { type: Number, default: 100 }, width: { type: Number, default: 350 }, height: { type: Number, default: 150 }, chartProps: { type: Object, default: () => { } }, thingName: { type: String, default: '' }, attr: { type: String, default: '' }, unit: { type: String, default: '' }, }, computed: { getStyle() { return { width: \`\${this.width}px\`,
height: \`\${this.height}px\`
} } }, setup(props) { const { onMounted, nextTick, toRefs, watch } = Vue; const { chartProps, currentData, thingName, attr, width, height } = toRefs(props);
let intervalInst = null; let myChart = null; const initChart = (data, pros) => { // 基于准备好的dom,初始化echarts实例
const dom = document.getElementById(props.chartId); if (dom) { if (!myChart) { myChart = echarts.init(dom); } // 由于实时推送时候不会重复创建实例,但是需更新画布大小。
myChart.resize({ width: width.value, height: height.value, }) if (data != null) { const { grid, codeConfig, range, progress, pointer, axisLine, axisTick, splitLine, nextNewLine, axisLabel, itemStyle, title, valueConfig, unit, outerCircleLine, innerCircleLine, innerCircle } = pros; // 指定图表的配置项和数据
// 轴线底色拼装
// 发现图表一直渲染的情况。就要注意图表数据多层对象嵌套的引用问题。
const newAxisLine = window._.cloneDeep(axisLine); const Colors = [] const oldColor = newAxisLine.lineStyle.color if (oldColor && oldColor.length > 0) { oldColor.forEach((item) => { Colors.push([item.ratio, item.color]) }) newAxisLine.lineStyle.color = Colors; } else if (oldColor && oldColor.length === 0) { delete newAxisLine.lineStyle.color }
let angle = 0;//角度,用来做简单的动画效果的
let biggerDigit = +data > 10000 let value = biggerDigit ? (+data/10000).toFixed(2) : +data.toFixed(2); const valueColor = valueConfig && (valueConfig.color || title.color); const valueSize = valueConfig && (valueConfig.fontSize || title.fontSize); const valueWeight = valueConfig && (valueConfig.fontWeight || 'normal'); const unitColor = unit && (unit.color || title.color); const unitSize = unit && (unit.fontSize || title.fontSize); const unitWeight = unit && (unit.fontWeight || 'normal'); const textFormat = nextNewLine ? '{a|' + value + (biggerDigit ? '万' : '') + '}\\r\\n{c|' + props.unit + '}' : '{a|' + value + '}{c|' + props.unit + '}'; const isWarning = (value || 0) > range.warnValue; splitLine.lineStyle.color = isWarning ? "#A59136" : splitLine.lineStyle.color; var option = { grid, title: { ...title, text: textFormat, x: 'center', y: 'center', textStyle: { rich: { a: { fontSize: valueSize, color: isWarning ? "#F0D048" : valueColor, fontWeight: valueWeight, align: 'center' },
c: { fontSize: unitSize, color: isWarning ? "#F0D048" : unitColor, fontWeight: unitWeight, align: 'center' } } } }, series: [ { name: 'innerProgressCircle', type: 'pie', radius: ['83%', '70%'], silent: true, startAngle: 90, z: 0, zlevel: 0, label: { normal: { position: "center",
} }, data: [{ value: value, name: "", itemStyle: { normal: { color: { // 完成的圆环的颜色
colorStops: [{ offset: 0, color: isWarning ? "#F0D048" : newAxisLine.lineStyle.color[0][1] // 0% 处的颜色
}, { offset: 1, color: isWarning ? "#F0D048" : newAxisLine.lineStyle.color[1][1] // 100% 处的颜色
}] }, } } }, { value: range.max - value, name: "", label: { normal: { show: false } }, itemStyle: { normal: { color: "transparent" } } } ] }, { name: "progressGuage", type: "gauge", radius: "83%", startAngle: 90, endAngle: -270, center: ['50%', '50%'], ...range, progress, pointer, axisLine: newAxisLine, axisTick, splitLine, axisLabel, itemStyle, hoverAnimation: true, detail: { show: false }, data: [{ value: value, name: "" }] },
] };
if (outerCircleLine.show) { option.series.push({ type: 'pie', name: 'outerCircleLine', radius: ['95%', '90%'], hoverAnimation: false, itemStyle: { normal: { color: isWarning ? "#A59136" : outerCircleLine.color } }, label: { show: false }, data: [100] }) }
if (innerCircleLine.show) { option.series.push(...[ { name: "ring5", type: 'custom', coordinateSystem: "none", renderItem: function (params, api) { return { type: 'arc', shape: { cx: api.getWidth() / 2, cy: api.getHeight() / 2, r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.83, startAngle: (0 + angle) * Math.PI / 180, endAngle: (90 + angle) * Math.PI / 180 }, style: { stroke: isWarning ? "#A59136" : innerCircleLine.color, fill: "transparent", lineWidth: 1.5 }, silent: true }; }, data: [0] }, { name: "ring5", type: 'custom', coordinateSystem: "none", renderItem: function (params, api) { return { type: 'arc', shape: { cx: api.getWidth() / 2, cy: api.getHeight() / 2, r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.83, startAngle: (180 + angle) * Math.PI / 180, endAngle: (270 + angle) * Math.PI / 180 }, style: { stroke: isWarning ? "#A59136" : innerCircleLine.color, fill: "transparent", lineWidth: 1.5 }, silent: true }; }, data: [0] }, { name: "ring5", type: 'custom', coordinateSystem: "none", renderItem: function (params, api) { return { type: 'arc', shape: { cx: api.getWidth() / 2, cy: api.getHeight() / 2, r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.83, startAngle: (270 + -angle) * Math.PI / 180, endAngle: (40 + -angle) * Math.PI / 180 }, style: { stroke: isWarning ? "#A59136" : innerCircleLine.color, fill: "transparent", lineWidth: 1.5 }, silent: true }; }, data: [0] }, { name: "ring5", type: 'custom', coordinateSystem: "none", renderItem: function (params, api) { return { type: 'arc', shape: { cx: api.getWidth() / 2, cy: api.getHeight() / 2, r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.83, startAngle: (90 + -angle) * Math.PI / 180, endAngle: (220 + -angle) * Math.PI / 180 }, style: { stroke: isWarning ? "#A59136" : innerCircleLine.color, fill: "transparent", lineWidth: 1.5 }, silent: true }; }, data: [0] }, { name: "ring5", type: 'custom', coordinateSystem: "none", renderItem: function (params, api) { let x0 = api.getWidth() / 2; let y0 = api.getHeight() / 2; let r = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.83; let point = getCirlPoint(x0, y0, r, (90 + -angle)) return { type: 'circle', shape: { cx: point.x, cy: point.y, r: 4 }, style: { stroke: isWarning ? "#A59136" : innerCircleLine.color, fill: "#0CD3DB" }, silent: true }; }, data: [0] }, { name: "ring5", //绿点
type: 'custom', coordinateSystem: "none", renderItem: function (params, api) { let x0 = api.getWidth() / 2; let y0 = api.getHeight() / 2; let r = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.83; let point = getCirlPoint(x0, y0, r, (270 + -angle)) return { type: 'circle', shape: { cx: point.x, cy: point.y, r: 4 }, style: { stroke: isWarning ? "#A59136" : innerCircleLine.color, //绿
fill: innerCircleLine.color, }, silent: true }; }, data: [0] } ]) }
if (innerCircle.show) { option.series.push({ type: 'pie', name: 'innerCircle', radius: [0, '83%'], hoverAnimation: false, animation: false, itemStyle: { normal: { shadowBlur: 20, shadowColor: '#000', color: isWarning ? "transparent" : innerCircle.backColor, borderWidth: 1, borderColor: isWarning ? "#A59136" : innerCircle.borderColor } }, label: { show: false }, data: [100] }) }
const func = new Function('option', 'datas', codeConfig); const opt = func(window._.cloneDeep(option), data);
// console.log('opt', opt);
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(opt);
function draw() { angle = angle + 3 myChart.setOption(opt, true) //window.requestAnimationFrame(draw);
} if (intervalInst) { clearInterval(intervalInst); } intervalInst = setInterval(function () { //用setInterval做动画感觉有问题
draw() }, 100); } } }
watch([currentData, chartProps], ([val, pros]) => { nextTick(() => { initChart(val, pros) }) }, { immediate: true, deep: true, }) }}
class CustomProgressGuageNode extends HtmlResize.view { realValue = defaultVal oldProperties = {} chartRendered = false instance = null
setHtml(rootEl) { if (!rootEl) return; const { properties, width, height } = this.props.model; const { normalData } = properties.dynamic || {} let thingName = 'pressure'; let attr = 'score'; if (normalData && normalData.dataPoint) { const dataPointStrParsed = JSON.parse(normalData.dataPoint || '{}') const { deviceCode, dataPoint } = dataPointStrParsed; thingName = deviceCode; attr = dataPoint.split(',')[0]; } if (this.instance) { // 实时数据不能推送一次就创建一次图表,可以在原有实例基础之上更改数据。
Object.assign(this.instance.component.props, { name: properties.nodeAlias, chartId: \`gauge-\${properties.id}\`,
currentData: this.realValue, width, height, chartProps: properties, thingName, attr, unit: normalData.unit || 'km/h' }) return } const el = document.createElement('div'); rootEl.innerHTML = ''; const instance = createVNode(ProgressGauge, { name: properties.nodeAlias, chartId: \`gauge-\${properties.id}\`,
currentData: this.realValue, width, height, chartProps: properties, thingName, attr, unit: normalData.unit || 'km/h' }) instance.appContext = app._context render(instance, el) rootEl.appendChild(el); this.instance = instance; }
sameProps(properties) { const isSame = window._.isEqual(this.oldProperties, properties); if (isSame) return true; this.oldProperties = properties; return false }
// 生命周期 支持重写内容, 但格式需一致
shouldUpdate() { const { properties } = this.props.model; const { normalData } = properties.dynamic || {};
if (normalData && !normalData.dataPoint && !normalData.defaultValue) { this.realValue = defaultVal; return true }
if (normalData) { const { defaultValue } = normalData || {}; if (defaultValue) { const realValue = window.resolveScadaNewValue(defaultValue) if (this.realValue !== Number(realValue)) { this.realValue = Number(realValue); return true; } } }
const propertiesBack = window._.cloneDeep(properties); if (propertiesBack.dynamic.normalData) { const isSameProps = this.sameProps(propertiesBack); if (isSameProps && this.chartRendered) { return false } else { if (!this.chartRendered) { this.chartRendered = true return true } if (!isSameProps) { return true; } } } }
updateHtml() { this.setHtml(this.rootEl); }
componentDidMount() { // 防止拖动时候频繁渲染图表
this.updateHtmlDebounced = window._.debounce(this.updateHtml.bind(this), 500); if (this.shouldUpdate()) { this.setHtml(this.rootEl); } }
componentDidUpdate() { if (this.shouldUpdate()) { this.updateHtmlDebounced(); } }}
class CustomProgressGaugeModel extends HtmlResize.model { initNodeData(data) { // 自定义组件,需最开始重���一下text 。
data.text = { value: "", x: data.x, y: data.y, };
super.initNodeData(data); const { properties } = this; this.width = properties.width || 80; this.height = properties.height || 35; this.text.editable = false; // 不允许文本被编辑
}
setAttributes() { // 自定义组件需重置 text
const { x, y, properties } = this; const { textHorizontalMove = 0, textVerticalMove = 0 } = properties; this.text = { ...this.text, x: x + textHorizontalMove, y: y + textVerticalMove, value: "", } }}
lf.register({ type: 'custom-progress-guage', view: CustomProgressGuageNode, model: CustomProgressGaugeModel,})`,css:"",fakeData:""},p={id:e,name:n,aliasName:t,image:a,imageType:i,groupName:l,groupType:o,isRemote:!1,isDefault:!0,sectionType:d,config:s,files:r};export{t as aliasName,s as config,p as default,r as files,l as groupName,o as groupType,e as id,a as image,i as imageType,c as isDefault,u as isRemote,n as name,d as sectionType};
|