使用javascript处理动态infograph的好方法?

使用javascript处理动态infograph的好方法?,javascript,html,canvas,Javascript,Html,Canvas,我目前被分配了一个使用javascript创建以下内容的项目,您可以在此处查看最终产品: 基本上,我的工作是获取提供的PDF并创建一种动态显示图像所传达的数据的方法。数据本身将在其他地方计算,所以我所要担心的是接受每个烧杯的值,并适当地填充它们 我现在的想法是: 现在我的想法是使用画布。我创建了一个烧杯类,然后将5个烧杯作为该类的实例。这很有效,我坐在画布上,在正确的位置有5个空烧杯。我把每个烧杯除以100;然后我可以正确地填充每一个像素的数量,不管它的百分比是多少,但这就是我遇到问题的地方。每

我目前被分配了一个使用javascript创建以下内容的项目,您可以在此处查看最终产品:

基本上,我的工作是获取提供的PDF并创建一种动态显示图像所传达的数据的方法。数据本身将在其他地方计算,所以我所要担心的是接受每个烧杯的值,并适当地填充它们

我现在的想法是:

现在我的想法是使用画布。我创建了一个烧杯类,然后将5个烧杯作为该类的实例。这很有效,我坐在画布上,在正确的位置有5个空烧杯。我把每个烧杯除以100;然后我可以正确地填充每一个像素的数量,不管它的百分比是多少,但这就是我遇到问题的地方。每个烧杯都是不同的形状,当每个烧杯装满时,形状也会改变。因此,我很难把烧杯里的液体吸进去。第二,如果我能正确地吸取液体,它将覆盖烧杯的细节。如果我先做液体,然后再做烧杯,那么问题正好相反。我也尝试过使用两个画布堆叠,并控制液体的不透明度,但没有任何运气得到我想要达到的效果


那么,有没有更好的方法来实现这一点,或者在画布上轻松地绘制奇怪的形状?我开始认为使用画布不是最好的方式。我知道我可以在不同的液位上为每个图像做几个图像,但是我想避免在最终的产品中使用这么多的图像。

< P>我不是数据可视化专家,这可能是一个多余的-但是你可能要考虑使用D3。JS:< /P>

这是一个非常灵活的绘图数据库。超级酷,看起来超级简单

这是一个图库\示例页面:

*不,我与D3.js没有任何关系


祝你好运!

我认为你应该用揭示的方法来解决这个问题

每个空烧杯一张图像,每个满液体一张图像,带有烧杯的详细信息

然后将液体图像放置在底部,并向上显示任意多个像素

<div class="beaker">
    <div class="liquid"></div>
</div>

上进行简单演示,这里有一种使用画布获得所需效果的方法:

  • 用透明的烧杯绘制图像
  • 从下到上逐渐绘制原始图像
  • 从而用液体填充透明烧杯

在使烧杯透明方面,你可以比我花更多的时间;)

当然,你可以把画分成几列,然后按你需要的速度把烧杯装满

如果需要不同的颜色来填充烧杯,可以使用context.globalCompositeOperation=“destination over”。此合成模式允许您在现有图形下“绘制”(新颜色将仅填充现有图像上的透明像素)

下面是代码和小提琴:


正文{背景色:象牙;}
#画布{边框:1px纯红;边框半径:15px;}
画布{位置:绝对;}
$(函数(){
window.requestAnimFrame=(函数(回调){
返回window.requestAnimationFrame | | | window.webkitRequestAnimationFrame | | | window.mozRequestAnimationFrame | | window.oRequestAnimationFrame | | window.msRequestAnimationFrame||
函数(回调){
设置超时(回调,1000/60);
};
})();
//绘制一个用灰色填充烧杯的背景
var background=document.getElementById(“背景”);
var bkCtx=background.getContext(“2d”);
bkCtx.fillStyle=“rgb(234234)”;
bkCtx.fillRect(0,0,背景.宽度,背景.高度);
var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
变量y;
var img1=新图像();
img1.onload=函数(){
ctx.drawImage(img1,0,0);
y=img1.height-50;
img2=新图像();
img2.onload=函数(){
制作动画();
}
img2.src=”https://dl.dropboxusercontent.com/u/139992952/temp01.png";
}
img1.src=”https://dl.dropboxusercontent.com/u/139992952/temp02.png";
var fps=30;
函数animate(){
setTimeout(函数(){

如果(我喜欢这个想法,但我的问题在于液体的隐藏。我有三件东西要显示,烧杯、背景和液体,到目前为止,我还没有想出一个像样的方案来正确显示它们。也许有什么方法可以将某个区域某个颜色的透明度设置为零?然后我可以简单地用星号表示使用装满的烧杯,并使其区域透明?@PeterJewicz添加了简单的代码和演示。你可以使用.png文件来实现透明。你所需要的只是烧杯是空的,烧杯装满了液体。你可以将烧杯与液体(也包括烧杯)重叠,只显示你想要的液体部分。。(由于使用了图像,演示值可能会很奇怪-通过谷歌找到..)
.beaker, .liquid {
    background: url('path-to-sprite-image.png') 0 100% no-repeat;
    width:130px;
}
.beaker {
    height:280px;
    position:relative;
}
.liquid {
    background-position: right 100%;
    bottom:0;
    left:0;
    position:absolute;
}
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    #canvas{border:1px solid red; border-radius:15px;}
    canvas{position:absolute;}
</style>

<script>
$(function(){

    window.requestAnimFrame = (function(callback) {
      return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
      function(callback) {
        window.setTimeout(callback, 1000 / 60);
      };
    })();


    // draw a background that fills the beakers with gray
    var background=document.getElementById("background");
    var bkCtx=background.getContext("2d");
    bkCtx.fillStyle="rgb(234,234,234)";
    bkCtx.fillRect(0,0,background.width,background.height);

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var y;

    var img1=new Image();
    img1.onload=function(){
        ctx.drawImage(img1,0,0);
        y=img1.height-50;
        img2=new Image();
        img2.onload=function(){
            animate();
        }
        img2.src="https://dl.dropboxusercontent.com/u/139992952/temp01.png";
    }
    img1.src="https://dl.dropboxusercontent.com/u/139992952/temp02.png";


    var fps = 30;
    function animate() {
        setTimeout(function() {

            if(y<100){return;}

            requestAnimFrame(animate);

            // Drawing code goes here
            y-=1;
            ctx.drawImage(img2,
                          0,y,img2.width,img2.height-y,
                          0,y,img2.width,img2.height-y)


        }, 1000 / fps);
    }


}); // end $(function(){});
</script>

</head>

<body>
    <canvas id="background" width=1024 height=327></canvas>
    <canvas id="canvas" width=1024 height=327></canvas>
</body>
</html>