Javascript 功能{ 返回xScaled[0]; } .消耗性,功能性{ 返回Y刻度[1]; }; } 函数pA,alpha,beta,x0,y0,t{ 设r=A*Math.expalpha*y0; 设arg=alpha*x0-beta*t; 设x=x0+r*Math.
功能{ 返回xScaled[0]; } .消耗性,功能性{ 返回Y刻度[1]; }; } 函数pA,alpha,beta,x0,y0,t{ 设r=A*Math.expalpha*y0; 设arg=alpha*x0-beta*t; 设x=x0+r*Math.cosarg; 设y=y0+r*Math.sinarg; 返回[x,y]; } 设置; 让timer=d3.timerstart; }; div.demo_容器{ 背景色:F1F1; } div.svg_容器{ 宽度:96%; 利润率:2%; } svg.demo{ 背景色:白色; 边框:实心1px浅灰色; }Javascript 功能{ 返回xScaled[0]; } .消耗性,功能性{ 返回Y刻度[1]; }; } 函数pA,alpha,beta,x0,y0,t{ 设r=A*Math.expalpha*y0; 设arg=alpha*x0-beta*t; 设x=x0+r*Math.,javascript,d3.js,Javascript,D3.js,功能{ 返回xScaled[0]; } .消耗性,功能性{ 返回Y刻度[1]; }; } 函数pA,alpha,beta,x0,y0,t{ 设r=A*Math.expalpha*y0; 设arg=alpha*x0-beta*t; 设x=x0+r*Math.cosarg; 设y=y0+r*Math.sinarg; 返回[x,y]; } 设置; 让timer=d3.timerstart; }; div.demo_容器{ 背景色:F1F1; } div.svg_容器{ 宽度:96%; 利润率:2%;
在这个例子中,我试图修复和减少代码-虽然没有明显的错误-它似乎是在一个非常小的块中渲染波浪-是的,如果我们也可以有一个d3v4版本-这里有什么区别-我的代码有什么问题?我已经更新了d3v4版本的代码。请查收。事实上我还没看过你的代码。我会检查一下。我们可以从那个旧的代码库导入其他属性-有很多其他的东西,比如改变水的颜色、速度、持续时间,其中一些在配置对象中被覆盖-我们还可以将这里的变量名从alpha0、beta0改为更容易理解的部分-这只创建了一个wave对象吗?可以添加具有不同属性的多个波吗?例如,如果我们想制作一个熔岩灯-不同的颜色/油,就像我想要的那样-这样你可以渲染外壳-作为矩形或圆形-在授予赏金之前,正在寻找各种改进
function loadLiquidFillGauge(elementId, value, config) {
if (config == null) config = liquidFillGaugeDefaultSettings();
const chart = d3.select(elementId[0])
.append("svg")
.attr("width", config.width)
.attr("height", config.height);
const gauge = chart
.append("g")
.attr('transform', 'translate(0,0)');
if(config.displayOverlay){
const imgs = chart
.append("g")
.attr('transform','translate(0,0)')
.append("svg:image")
.attr("xlink:href", config.overlayImageSrc)
.attr("x", "0")
.attr("y", "0")
.attr("width", config.overlayImageWidth)
.attr("height", config.overlayImageHeight);
}
if(config.axisLabel){
const axisLabel = chart
.append("g")
.append("text")
.attr("x", config.width/2)
.attr("y", config.height)
.attr("dy", "-4px")
.style("text-anchor", "middle")
.text(config.axisLabel)
.call(wrap, (config.width / 2)-18);//add some padding
config.height = config.height - 40;//with the label in place reduce the height of the chart
}
const randId = 'liquid_';
var radius = Math.min(parseInt(config.width), parseInt(config.height)) / 2;
radius = config.height / 2;
var locationX = -parseInt(config.width) / 2;
var locationY = parseInt(config.height) / 2 - radius;
if (config.fillShape == "rect") {
locationY = 0;
}
const fillPercent = Math.max(config.minValue, Math.min(config.maxValue, value)) / config.maxValue;
let waveHeightScale = null;
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]);
}
const textPixels = (config.textSize * radius / 2);
const textFinalValue = parseFloat(value).toFixed(2);
const textStartValue = config.valueCountUp ? config.minValue : textFinalValue;
const percentText = config.displayPercent ? "%" : "";
const circleThickness = config.circleThickness * radius;
const circleFillGap = config.circleFillGap * radius;
const fillCircleMargin = circleThickness + circleFillGap;
const fillCircleRadius = radius - fillCircleMargin;
const waveHeight = fillCircleRadius * waveHeightScale(fillPercent * 100);
const waveLength = config.width * 2 / config.waveCount;
const waveClipCount = 1 + config.waveCount;
const waveClipWidth = waveLength * waveClipCount;
// Data for building the clip wave area.
const data = [];
for (let i = 0; i <= 40 * waveClipCount; i++) {
data.push({
x: i / (40 * waveClipCount),
y: (i / (40))
});
}
// Scales for drawing the outer circle.
const gaugeCircleX = d3.scaleLinear().range([0, 2 * Math.PI]).domain([0, 1]);
const gaugeCircleY = d3.scaleLinear().range([0, radius]).domain([0, radius]);
// Scales for controlling the size of the clipping path.
const waveScaleX = d3.scaleLinear().range([0, waveClipWidth]).domain([0, 1]);
const waveScaleY = d3.scaleLinear().range([0, waveHeight]).domain([0, 1]);
// Scales for controlling the position of the clipping path.
// The clipping area size is the height of the fill circle + the wave height, so we position the clip wave
// such that the it will overlap the fill circle at all when at 0%, and will totally cover the fill
// circle at 100%.
const waveRiseScale = d3.scaleLinear()
.range([(fillCircleMargin + fillCircleRadius * 2 + waveHeight), (fillCircleMargin - waveHeight)])
.domain([0, 1]);
const waveAnimateScale = d3.scaleLinear()
.range([0, waveClipWidth - fillCircleRadius * 2]) // Push the clip area one full wave then snap back.
.domain([0, 1]);
// Center the gauge within the parent SVG.
const gaugeGroup = gauge.append("g")
.attr('transform', 'translate(' + locationX + ',' + locationY + ')');
var drawOuterBlock = function() {
// Draw the outer block.
gaugeGroup.append("rect")
.attr("x", config.width / 2)
.attr("y", 0)
.attr("width", config.width)
.attr("height", config.height)
.style("fill", config.backgroundColor);
}
drawOuterBlock();
// The clipping wave area.
const clipArea = d3.area()
.x(function(d) {
return waveScaleX(d.x);
})
.y0(function(d) {
return waveScaleY(Math.sin(Math.PI * 2 * config.waveOffset * -1 + Math.PI * 2 * (1 - config.waveCount) + d.y * 2 * Math.PI));
});
clipArea
.y1(function(d) {
return (fillCircleRadius * 2 + waveHeight);
});
//.y1(function(d) { return (config.height - (fillCircleRadius * 2) + waveHeight); } );
const waveGroup = gaugeGroup.append("defs")
.append("clipPath")
.attr("id", "clipWave" + randId);
const wave = waveGroup.append("path")
.datum(data)
.attr("d", clipArea)
.attr("T", 0);
// The inner circle with the clipping wave attached.
const fillGroup = gaugeGroup.append("g")
.attr("clip-path", "url(#clipWave" + randId + ")");
var drawShapeWave = function(shape) {
// Draw the wave shape.
//console.log("config.width", config.width);
//console.log("config.height", config.height);
//console.log("config.margin", config.margin);
fillGroup.append("rect")
.attr("x", config.width / 2 + config.margin)
.attr("y", config.margin)
.attr("width", config.width - 2 * config.margin)
.attr("height", config.height - 2 * config.margin)
fillGroup
.style("fill", config.waveStartColor)
.transition()
.duration(config.waveColorDuration)
.style("fill", config.waveColor);
}
drawShapeWave(config.fillShape);
// Make the wave rise. wave and waveGroup are separate so that horizontal and vertical movement can be controlled independently.
const waveGroupXPosition = -config.width / 2;
if (config.waveRise) {
waveGroup.attr('transform', 'translate(' + waveGroupXPosition + ',' + waveRiseScale(0) + ')')
.transition()
.duration(config.waveRiseTime)
.attr('transform', 'translate(' + waveGroupXPosition + ',' + waveRiseScale(fillPercent) + ')')
.on("start", function() {
wave.attr('transform', 'translate(1,0)');
}); // This transform is necessary to get the clip wave positioned correctly when waveRise=true and waveAnimate=false. The wave will not position correctly without this, but it's not clear why this is actually necessary.
} else {
waveGroup.attr('transform', 'translate(' + waveGroupXPosition + ',' + waveRiseScale(fillPercent) + ')');
}
if (config.waveAnimate) animateWave();
function animateWave() {
wave.attr('transform', 'translate(0,0)');
wave.transition()
.duration(config.waveAnimateTime)
.ease(d3.easeLinear)
.attr('transform', `translate(${config.width},0)`)
.on('end', animateWave);
}
}