d3js 源码地址:: http://bl.ocks.org/brattonc/5e5ce9beee483220e2f6
官方提供的代码不能直接用,版本3.x 这是调整后v5能使用的。
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<title>7</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
<link rel="stylesheet" type="text/css" href="/css.css" />
</head>
<body>
<svg id="svg" width="300" height="300" onclick="javascript:gauge.update(NewValue())"></svg>
<span>点击SVG更新数据</span>
</body>
<script type='text/javascript'>
var gauge = loadLiquidFillGauge("svg", 55, {
circleColor: "#FF7777",
textColor: "#FF4444",
waveTextColor: "#FFAAAA",
waveColor: "#FFDDDD",
circleThickness: 0.02,
circleFillGap: 0,
textVertPosition: 0.2,
waveAnimateTime: 1000,
waveRiseTime: 3000
});
function NewValue() {
if (Math.random() > .5) {
return Math.round(Math.random() * 100);
}
return (Math.random() * 100).toFixed(1);
}
function loadLiquidFillGauge(elementId, value, config) {
config = Object.assign({}, {
minValue: 0, // 量规最小值.
maxValue: 100, // 量规最大值.
circleThickness: 0.05, // 外圆的厚度与半径的百分比.
circleFillGap: 0.05, // 外圆与波圆之间的间隙大小与外圆半径的百分比.
circleColor: "#178BCA", // 外圆的颜色.
waveHeight: 0.05, // 波高与波圆半径的百分比.
waveCount: 2, // 每波圈宽度的全波数.
waveRiseTime: 1000, // 波从0上升到最终高度所需的时间,以毫秒为单位.
waveAnimateTime: 18000, // 一个完整的波进入波圈的时间(以毫秒为单位).
waveRise: true, // 控制波浪是否应该从0上升到它的全部高度,或从它的全部高度开始
waveHeightScaling: true, // 控制波大小缩放在低和高填充百分比。当真值时,波高在50%填充时达到最大值,在0%和100%填充时达到最小值。这有助于防止波使波圈出现完全满或空时,接近它的最小或最大填充。
waveAnimate: true, // 控制波形是滚动还是静态.
waveColor: "#178BCA", // 填充波的颜色。
waveOffset: 0, // 最初抵消波的量。0 = 无偏移。1 = 一个完整波的偏移量
textVertPosition: .5, // 在波圈内显示百分比文本的高度。0 =下,1 =上.
textSize: 1, // 要在波圈中显示的文本的相对高度。1 = 50%
valueCountUp: true, // 如果为真,则显示的值从0计数到加载时的最终值。如果为false,则显示最终值。
displayPercent: true, // 如果为真,值后面会显示%符号。
textColor: "#045681", // 当波浪不重叠值文本时的颜色。
waveTextColor: "#A4DBf8" // 当波浪与值文本重叠时的颜色.
}, config);
var gauge = d3.select("#" + elementId);
var radius = Math.min(parseInt(gauge.style("width")), parseInt(gauge.style("height"))) / 2;
var locationX = parseInt(gauge.style("width")) / 2 - radius;
var locationY = parseInt(gauge.style("height")) / 2 - radius;
var fillPercent = Math.max(config.minValue, Math.min(config.maxValue, value)) / config.maxValue;
var waveHeightScale;
if (config.waveHeightScaling) {
waveHeightScale = d3.scaleLinear().range([0, config.waveHeight, 0]).domain([0, 50, 100]);
} else {
waveHeightScale = d3.scaleLinear().range([config.waveHeight, config.waveHeight]).domain([0, 100]);
}
var textPixels = (config.textSize * radius / 2);
var textFinalValue = parseFloat(value).toFixed(2);
var textStartValue = config.valueCountUp ? config.minValue : textFinalValue;
var percentText = config.displayPercent ? "%" : "";
var circleThickness = config.circleThickness * radius;
var circleFillGap = config.circleFillGap * radius;
var fillCircleMargin = circleThickness + circleFillGap;
var fillCircleRadius = radius - fillCircleMargin;
var waveHeight = fillCircleRadius * waveHeightScale(fillPercent * 100);
var waveLength = fillCircleRadius * 2 / config.waveCount;
var waveClipCount = 1 + config.waveCount;
var waveClipWidth = waveLength * waveClipCount;
// 四舍五入函数,以便在数值累计时始终显示正确的小数点后位数。
var textRounder = (value) => Math.round(value);
if (parseFloat(textFinalValue) != parseFloat(textRounder(textFinalValue))) {
textRounder = (value) => parseFloat(value).toFixed(1);
}
if (parseFloat(textFinalValue) != parseFloat(textRounder(textFinalValue))) {
textRounder = (value) => parseFloat(value).toFixed(2);
}
// 建立clip wave区域的数据。
var data = Array.from({ length: 41 * waveClipCount }, (_, i) => ({ x: i / (40 * waveClipCount), y: (i / (40)) }));
// 绘制外圆的比例。
var gaugeCircleX = d3.scaleLinear().range([0, 2 * Math.PI]).domain([0, 1]);
var gaugeCircleY = d3.scaleLinear().range([0, radius]).domain([0, radius]);
// 用于控制剪切路径大小的尺度。
var waveScaleX = d3.scaleLinear().range([0, waveClipWidth]).domain([0, 1]);
var waveScaleY = d3.scaleLinear().range([0, waveHeight]).domain([0, 1]);
// 用于控制裁剪路径位置的刻度。
var waveRiseScale = d3.scaleLinear()
// 剪辑区域的大小是填充圆的高度+波的高度,所以我们定位剪辑波这样,它将重叠填充圆在所有0%时,并将完全覆盖填充圆在100%。
.range([(fillCircleMargin + fillCircleRadius * 2 + waveHeight), (fillCircleMargin - waveHeight)]).domain([0, 1]);
var waveAnimateScale = d3.scaleLinear()
.range([0, waveClipWidth - fillCircleRadius * 2]) // 将夹子区域推一个完整的波,然后弹回来。
.domain([0, 1]);
// 用于控制文本在量规内的位置的刻度。
var textRiseScaleY = d3.scaleLinear()
.range([fillCircleMargin + fillCircleRadius * 2, (fillCircleMargin + textPixels * 0.7)])
.domain([0, 1]);
// 在父SVG中居中测量。
var gaugeGroup = gauge.append("g").attr('transform', `translate(${locationX},${locationY})`);
// 画一个外圆。
var gaugeCircleArc = d3.arc()({
startAngle: gaugeCircleX(0),
endAngle: gaugeCircleX(1),
outerRadius: gaugeCircleY(radius),
innerRadius: gaugeCircleY(radius - circleThickness),
})
gaugeGroup.append("path")
.attr("d", gaugeCircleArc)
.style("fill", config.circleColor)
.attr('transform', `translate(${radius},${radius})`);
// 波不重叠的文本。
var text1 = gaugeGroup.append("text")
.text(textRounder(textStartValue) + percentText)
.attr("class", "liquidFillGaugeText")
.attr("text-anchor", "middle")
.attr("font-size", textPixels + "px")
.style("fill", config.textColor)
.attr('transform', `translate(${radius},${textRiseScaleY(config.textVertPosition)})`);
// 剪切波面积。
var clipArea = d3.area()
.x(d => waveScaleX(d.x))
.y0(d => waveScaleY(Math.sin(Math.PI * 2 * config.waveOffset * -1 + Math.PI * 2 * (1 - config.waveCount) + d.y * 2 * Math.PI)))
.y1(d => (fillCircleRadius * 2 + waveHeight));
var waveGroup = gaugeGroup.append("defs").append("clipPath").attr("id", "clipWave" + elementId);
var wave = waveGroup.append("path")
.datum(data)
.attr("d", clipArea)
.attr("T", 0);
// 带有剪切波的内圆。
var fillCircleGroup = gaugeGroup.append("g").attr("clip-path", "url(#clipWave" + elementId + ")");
fillCircleGroup.append("circle")
.attr("cx", radius)
.attr("cy", radius)
.attr("r", fillCircleRadius)
.style("fill", config.waveColor);
// 波重叠的文本。
var text2 = fillCircleGroup.append("text")
.text(textRounder(textStartValue) + percentText)
.attr("class", "liquidFillGaugeText")
.attr("text-anchor", "middle")
.attr("font-size", textPixels + "px")
.style("fill", config.waveTextColor)
.attr('transform', `translate(${radius},${textRiseScaleY(config.textVertPosition)})`);
// 把数值加起来。
if (config.valueCountUp) {
var textTween = function () {
var i = d3.interpolate(this.textContent, textFinalValue);
return function (t) {
this.textContent = textRounder(i(t)) + percentText;
}
};
text1.transition().duration(config.waveRiseTime).tween("text", textTween);
text2.transition().duration(config.waveRiseTime).tween("text", textTween);
}
// 让波浪上升。波和波组是分开的,水平和垂直运动可以独立控制。
var waveGroupXPosition = fillCircleMargin + fillCircleRadius * 2 - waveClipWidth;
if (config.waveRise) {
waveGroup.attr('transform', `translate(${waveGroupXPosition},${waveRiseScale(0)})`)
.transition()
.duration(config.waveRiseTime)
.ease(d3.easeLinear)
.attr('transform', `translate(${waveGroupXPosition},${waveRiseScale(fillPercent)})`)
.on("start", function () {// 当wave Rise = true和 wave Animate=false时,这个变换是必要的,以使剪辑波正确定位。如果没有这个,波将无法正确定位,但我们不清楚为什么这是必要的.
wave.attr('transform', 'translate(1,0)');
});
} else {
waveGroup.attr('transform', `translate(${waveGroupXPosition},${waveRiseScale(fillPercent)}`);
}
if (config.waveAnimate) animateWave();
function animateWave() {
wave.attr('transform', `translate(${waveAnimateScale(wave.attr('T'))},0)`);
wave.transition()
.duration(config.waveAnimateTime * (1 - wave.attr('T')))
.ease(d3.easeLinear)
.attr("transform", `translate(${waveAnimateScale(1)},0)`)
.attr('T', 1)
.on('end', function () {
wave.attr('T', 0);
animateWave();
});
}
function GaugeUpdater() {
this.update = function (value) {
var newFinalValue = parseFloat(value).toFixed(2);
var textRounderUpdater = (value) => Math.round(value);
if (parseFloat(newFinalValue) != parseFloat(textRounderUpdater(newFinalValue))) {
textRounderUpdater = (value) => parseFloat(value).toFixed(1);
}
if (parseFloat(newFinalValue) != parseFloat(textRounderUpdater(newFinalValue))) {
textRounderUpdater = (value) => parseFloat(value).toFixed(2);
}
var textTween = function () {
var interpolate = d3.interpolate(this.textContent, parseFloat(value).toFixed(2));
return function (t) {
this.textContent = textRounderUpdater(interpolate(t)) + percentText;
}
};
text1.transition().duration(config.waveRiseTime).tween("text", textTween);
text2.transition().duration(config.waveRiseTime).tween("text", textTween);
var fillPercent = Math.max(config.minValue, Math.min(config.maxValue, value)) / config.maxValue;
var waveHeight = fillCircleRadius * waveHeightScale(fillPercent * 100);
var waveRiseScale = d3.scaleLinear()
// 剪辑区域的大小是填充圆的高度+波的高度,所以我们定位剪辑波这样,它将重叠填充圆在所有0%时,并将完全覆盖填充圆在100%.
.range([(fillCircleMargin + fillCircleRadius * 2 + waveHeight), (fillCircleMargin - waveHeight)])
.domain([0, 1]);
var newHeight = waveRiseScale(fillPercent);
var waveScaleX = d3.scaleLinear().range([0, waveClipWidth]).domain([0, 1]);
var waveScaleY = d3.scaleLinear().range([0, waveHeight]).domain([0, 1]);
var newClipArea;
if (config.waveHeightScaling) {
newClipArea = d3.area()
.x(d => waveScaleX(d.x))
.y0(d => waveScaleY(Math.sin(Math.PI * 2 * config.waveOffset * -1 + Math.PI * 2 * (1 - config.waveCount) + d.y * 2 * Math.PI)))
.y1(d => (fillCircleRadius * 2 + waveHeight));
} else {
newClipArea = clipArea;
}
var newWavePosition = config.waveAnimate ? waveAnimateScale(1) : 0;
wave.transition()
.duration(0)
.transition()
.duration(config.waveAnimate ? (config.waveAnimateTime * (1 - wave.attr('T'))) : (config.waveRiseTime))
.ease(d3.easeCircle)
.attr('d', newClipArea)
.attr('transform', `translate(${newWavePosition},0)`)
.attr('T', '1')
.on("end", function () {
if (config.waveAnimate) {
wave.attr('transform', `translate(${waveAnimateScale(0)},0)`)
animateWave();
}
});
waveGroup.transition()
.duration(config.waveRiseTime)
.attr('transform', `translate(${waveGroupXPosition},${newHeight})`)
}
}
return new GaugeUpdater();
}
</script>
</html>
组件版本
<template>
<div style="width: 100%;height: 300px;" class="p-30"></div>
</template>
<script>
import * as d3 from "d3";
export default {
name: 'loadLiquidFillGauge',
data() {
return {
instance: null
}
},
props: {
step: { type: [Number, String], default: 0.01 },
},
mounted() {
this.instance = this.loadLiquidFillGauge(this.$el, this.step, {
circleThickness: 0.05, // 外圆的厚度与半径的百分比.
circleFillGap: 0.05, // 外圆与波圆之间的间隙大小与外圆半径的百分比.
circleColor: "#409EFF", // 外圆的颜色.
waveHeight: 0.05, // 波高与波圆半径的百分比.
waveCount: 2, // 每波圈宽度的全波数.
waveRiseTime: 2000, // 波从0上升到最终高度所需的时间,以毫秒为单位.
waveAnimateTime: 1000, // 一个完整的波进入波圈的时间(以毫秒为单位).
waveColor: "#409EFF", // 填充波的颜色。
displayPercent: "ms", // 如果为真,值后面会显示%符号。
textColor: "#045681", // 当波浪不重叠值文本时的颜色。
waveTextColor: "#fff", // 当波浪与值文本重叠时的颜色.
});
},
methods: {
loadLiquidFillGauge(element, value, config) {
config = Object.assign({}, {
minValue: 0, // 量规最小值.
maxValue: 100, // 量规最大值.
circleThickness: 0.05, // 外圆的厚度与半径的百分比.
circleFillGap: 0.05, // 外圆与波圆之间的间隙大小与外圆半径的百分比.
circleColor: "#178BCA", // 外圆的颜色.
waveHeight: 0.05, // 波高与波圆半径的百分比.
waveCount: 2, // 每波圈宽度的全波数.
waveRiseTime: 1000, // 波从0上升到最终高度所需的时间,以毫秒为单位.
waveAnimateTime: 18000, // 一个完整的波进入波圈的时间(以毫秒为单位).
waveRise: true, // 控制波浪是否应该从0上升到它的全部高度,或从它的全部高度开始
waveHeightScaling: true, // 控制波大小缩放在低和高填充百分比。当真值时,波高在50%填充时达到最大值,在0%和100%填充时达到最小值。这有助于防止波使波圈出现完全满或空时,接近它的最小或最大填充。
waveAnimate: true, // 控制波形是滚动还是静态.
waveColor: "#178BCA", // 填充波的颜色。
waveOffset: 0, // 最初抵消波的量。0 = 无偏移。1 = 一个完整波的偏移量
textVertPosition: .5, // 在波圈内显示百分比文本的高度。0 =下,1 =上.
textSize: .8, // 要在波圈中显示的文本的相对高度。1 = 50%
valueCountUp: true, // 如果为真,则显示的值从0计数到加载时的最终值。如果为false,则显示最终值。
displayPercent: "%", // 后面会显示%符号。
textColor: "#045681", // 当波浪不重叠值文本时的颜色。
waveTextColor: "#A4DBf8" // 当波浪与值文本重叠时的颜色.
}, config);
var gauge = d3.select(element).append('svg').attr('width', '100%').attr('height', '100%');
var radius = Math.min(parseInt(gauge.style("width")), parseInt(gauge.style("height"))) / 2;
var locationX = parseInt(gauge.style("width")) / 2 - radius;
var locationY = parseInt(gauge.style("height")) / 2 - radius;
var fillPercent = Math.max(config.minValue, Math.min(config.maxValue, value)) / config.maxValue;
var waveHeightScale;
if (config.waveHeightScaling) {
waveHeightScale = d3.scaleLinear().range([0, config.waveHeight, 0]).domain([0, 50, 100]);
} else {
waveHeightScale = d3.scaleLinear().range([config.waveHeight, config.waveHeight]).domain([0, 100]);
}
var textPixels = (config.textSize * radius / 3);
var textFinalValue = parseFloat(value).toFixed(2);
var textStartValue = config.valueCountUp ? config.minValue : textFinalValue;
var percentText = config.displayPercent;
var circleThickness = config.circleThickness * radius;
var circleFillGap = config.circleFillGap * radius;
var fillCircleMargin = circleThickness + circleFillGap;
var fillCircleRadius = radius - fillCircleMargin;
var waveHeight = fillCircleRadius * waveHeightScale(fillPercent * 100);
var waveLength = fillCircleRadius * 2 / config.waveCount;
var waveClipCount = 1 + config.waveCount;
var waveClipWidth = waveLength * waveClipCount;
// 四舍五入函数,以便在数值累计时始终显示正确的小数点后位数。
var textRounder = (value) => Math.round(value);
if (parseFloat(textFinalValue) != parseFloat(textRounder(textFinalValue))) {
textRounder = (value) => parseFloat(value).toFixed(1);
}
if (parseFloat(textFinalValue) != parseFloat(textRounder(textFinalValue))) {
textRounder = (value) => parseFloat(value).toFixed(2);
}
// 建立clip wave区域的数据。
var data = Array.from({ length: 41 * waveClipCount }, (_, i) => ({ x: i / (40 * waveClipCount), y: (i / (40)) }));
// 绘制外圆的比例。
var gaugeCircleX = d3.scaleLinear().range([0, 2 * Math.PI]).domain([0, 1]);
var gaugeCircleY = d3.scaleLinear().range([0, radius]).domain([0, radius]);
// 用于控制剪切路径大小的尺度。
var waveScaleX = d3.scaleLinear().range([0, waveClipWidth]).domain([0, 1]);
var waveScaleY = d3.scaleLinear().range([0, waveHeight]).domain([0, 1]);
// 用于控制裁剪路径位置的刻度。
var waveRiseScale = d3.scaleLinear()
// 剪辑区域的大小是填充圆的高度+波的高度,所以我们定位剪辑波这样,它将重叠填充圆在所有0%时,并将完全覆盖填充圆在100%。
.range([(fillCircleMargin + fillCircleRadius * 2 + waveHeight), (fillCircleMargin - waveHeight)]).domain([0, 1]);
var waveAnimateScale = d3.scaleLinear()
.range([0, waveClipWidth - fillCircleRadius * 2]) // 将夹子区域推一个完整的波,然后弹回来。
.domain([0, 1]);
// 用于控制文本在量规内的位置的刻度。
var textRiseScaleY = d3.scaleLinear()
.range([fillCircleMargin + fillCircleRadius * 2, (fillCircleMargin + textPixels * 0.7)])
.domain([0, 1]);
// 在父SVG中居中测量。
var gaugeGroup = gauge.append("g").attr('transform', `translate(${locationX},${locationY})`);
// 画一个外圆。
var gaugeCircleArc = d3.arc()({
startAngle: gaugeCircleX(0),
endAngle: gaugeCircleX(1),
outerRadius: gaugeCircleY(radius),
innerRadius: gaugeCircleY(radius - circleThickness),
})
gaugeGroup.append("path")
.attr("d", gaugeCircleArc)
.style("fill", config.circleColor)
.attr('transform', `translate(${radius},${radius})`);
// 波不重叠的文本。
var text1 = gaugeGroup.append("text")
.text(textRounder(textStartValue) + percentText)
.attr("class", "liquidFillGaugeText")
.attr("text-anchor", "middle")
.attr("font-size", textPixels + "px")
.style("fill", config.textColor)
.attr('transform', `translate(${radius},${textRiseScaleY(config.textVertPosition)})`);
// 剪切波面积。
var clipArea = d3.area()
.x(d => waveScaleX(d.x))
.y0(d => waveScaleY(Math.sin(Math.PI * 2 * config.waveOffset * -1 + Math.PI * 2 * (1 - config.waveCount) + d.y * 2 * Math.PI)))
.y1(d => (fillCircleRadius * 2 + waveHeight));
var waveGroup = gaugeGroup.append("defs").append("clipPath").attr("id", "clipWave" + 'svg');
var wave = waveGroup.append("path")
.datum(data)
.attr("d", clipArea)
.attr("T", 0);
// 带有剪切波的内圆。
var fillCircleGroup = gaugeGroup.append("g").attr("clip-path", "url(#clipWave" + 'svg' + ")");
fillCircleGroup.append("circle")
.attr("cx", radius)
.attr("cy", radius)
.attr("r", fillCircleRadius)
.style("fill", config.waveColor);
// 波重叠的文本。
var text2 = fillCircleGroup.append("text")
.text(textRounder(textStartValue) + percentText)
.attr("class", "liquidFillGaugeText")
.attr("text-anchor", "middle")
.attr("font-size", textPixels + "px")
.style("fill", config.waveTextColor)
.attr('transform', `translate(${radius},${textRiseScaleY(config.textVertPosition)})`);
// 把数值加起来。
if (config.valueCountUp) {
var textTween = function () {
var i = d3.interpolate(this.textContent, textFinalValue);
return function (t) {
this.textContent = textRounder(i(t)) + percentText;
}
};
text1.transition().duration(config.waveRiseTime).tween("text", textTween);
text2.transition().duration(config.waveRiseTime).tween("text", textTween);
}
// 让波浪上升。波和波组是分开的,水平和垂直运动可以独立控制。
var waveGroupXPosition = fillCircleMargin + fillCircleRadius * 2 - waveClipWidth;
if (config.waveRise) {
waveGroup.attr('transform', `translate(${waveGroupXPosition},${waveRiseScale(0)})`)
.transition()
.duration(config.waveRiseTime)
.ease(d3.easeLinear)
.attr('transform', `translate(${waveGroupXPosition},${waveRiseScale(fillPercent)})`)
.on("start", function () {// 当wave Rise = true和 wave Animate=false时,这个变换是必要的,以使剪辑波正确定位。如果没有这个,波将无法正确定位,但我们不清楚为什么这是必要的.
wave.attr('transform', 'translate(1,0)');
});
} else {
waveGroup.attr('transform', `translate(${waveGroupXPosition},${waveRiseScale(fillPercent)}`);
}
if (config.waveAnimate) animateWave();
function animateWave() {
wave.attr('transform', `translate(${waveAnimateScale(wave.attr('T'))},0)`);
wave.transition()
.duration(config.waveAnimateTime * (1 - wave.attr('T')))
.ease(d3.easeLinear)
.attr("transform", `translate(${waveAnimateScale(1)},0)`)
.attr('T', 1)
.on('end', function () {
wave.attr('T', 0);
animateWave();
});
}
function GaugeUpdater() {
this.update = function (value) {
var newFinalValue = parseFloat(value).toFixed(2);
var textRounderUpdater = (value) => Math.round(value);
if (parseFloat(newFinalValue) != parseFloat(textRounderUpdater(newFinalValue))) {
textRounderUpdater = (value) => parseFloat(value).toFixed(1);
}
if (parseFloat(newFinalValue) != parseFloat(textRounderUpdater(newFinalValue))) {
textRounderUpdater = (value) => parseFloat(value).toFixed(2);
}
var textTween = function () {
var interpolate = d3.interpolate(this.textContent, parseFloat(value).toFixed(2));
return function (t) {
this.textContent = textRounderUpdater(interpolate(t)) + percentText;
}
};
text1.transition().duration(config.waveRiseTime).tween("text", textTween);
text2.transition().duration(config.waveRiseTime).tween("text", textTween);
var _max = Math.max(config.minValue, Math.min(config.maxValue, value));
var fillPercent = (value <= config.maxValue ? _max : 85) / config.maxValue;
var waveHeight = fillCircleRadius * waveHeightScale(fillPercent * 100);
var waveRiseScale = d3.scaleLinear()
// 剪辑区域的大小是填充圆的高度+波的高度,所以我们定位剪辑波这样,它将重叠填充圆在所有0%时,并将完全覆盖填充圆在100%.
.range([(fillCircleMargin + fillCircleRadius * 2 + waveHeight), (fillCircleMargin - waveHeight)])
.domain([0, 1]);
var newHeight = waveRiseScale(fillPercent);
var waveScaleX = d3.scaleLinear().range([0, waveClipWidth]).domain([0, 1]);
var waveScaleY = d3.scaleLinear().range([0, waveHeight]).domain([0, 1]);
var newClipArea;
if (config.waveHeightScaling) {
newClipArea = d3.area()
.x(d => waveScaleX(d.x))
.y0(d => waveScaleY(Math.sin(Math.PI * 2 * config.waveOffset * -1 + Math.PI * 2 * (1 - config.waveCount) + d.y * 2 * Math.PI)))
.y1(d => (fillCircleRadius * 2 + waveHeight));
} else {
newClipArea = clipArea;
}
var newWavePosition = config.waveAnimate ? waveAnimateScale(1) : 0;
wave.transition()
.duration(0)
.transition()
.duration(config.waveAnimate ? (config.waveAnimateTime * (1 - wave.attr('T'))) : (config.waveRiseTime))
.ease(d3.easeCircle)
.attr('d', newClipArea)
.attr('transform', `translate(${newWavePosition},0)`)
.attr('T', '1')
.on("end", function () {
if (config.waveAnimate) {
wave.attr('transform', `translate(${waveAnimateScale(0)},0)`)
animateWave();
}
});
waveGroup.transition()
.duration(config.waveRiseTime)
.attr('transform', `translate(${waveGroupXPosition},${newHeight})`)
}
}
return new GaugeUpdater();
},
update(val) {
this.instance.update(val);
}
}
// End
}
</script>
// 使用该组件
<load-liquid-fill-gauge ref="gauge" step="80" />