1

I'm trying to create my first animated scatterplot with pixi.js and I don't understand how to update it with new data on click-event (newdata is stored in "newDaraForUpdate" variable).

I'm searching for something like d3 general update pattern that allows to redraw one data to another and remove unnecessary points or append new points if it is necessary. This is my code:

var parseDate = d3.timeParse("%Y-%m-%d");
var $windowWidth = $(window).width();
var $windowHeight = $(window).height();

PIXI.utils.skipHello(); // remove pixi message in console log 

var app = new PIXI.Application($windowWidth, $windowHeight, {transparent:true, resolution:1});
$('#canvas-container').append(app.view);

d3.csv("data/data.csv", function(chartData){

    chartData.forEach(function (d) {           
        d.completion = parseDate(d.completion)
    });

    preparedData = chartData.filter(function(d) {
    return d.service === "1";
    });

    newDaraForUpdate = chartData.filter(function(d) {
    return d.service === "2";
    });


    var xScale = fc.scaleDiscontinuous(d3.scaleTime())
        .discontinuityProvider(fc.discontinuitySkipWeekends());

    xScale.domain([parseDate("2017-01-01"), parseDate("2017-12-31")])
        .range([0, $windowWidth]);

    var yScale = d3.scaleLinear()
        .domain([0, 160])
        .range([$windowHeight, 0]);

    var particleColors = d3.scaleOrdinal() // D3 Version 4
        .domain(["1", "2", "3", "4"])
        .range(["cccccc", "E58903", "7EB852", "ff0702"]);

    var particleCount = preparedData.length;   

    var particleSettings;

    preparedData.forEach(function(d) {
        particleSettings = {
            particleSize: 10,
            x: xScale(d.registration),
            y: yScale(d.counterTotal),
            scale: 0.2,
            alpha: 0.7,
            particleSpeed: 1,
            color: particleColors(d.color)
        };
        createParticle(particleSettings);
    });   

    function createParticle() {

        var graphic = new PIXI.Graphics(); // create graphic
        graphic.beginFill('0x' + particleSettings.color);
        graphic.drawCircle(0, 0, particleSettings.particleSize); // (x, y, radius) // gets scaled as a sprite later
        graphic.endFill();

        var texture = graphic.generateCanvasTexture(); // create texture using graphic (scaleMode, resolution)
        texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST; // scale mode for pixelation

        var particleSprite = new PIXI.Sprite(texture);  // create particle using texture
        particleSprite.interactive = true;                        // enable mouse and touch events
        particleSprite.buttonMode = true;                         // show hand cursor on mouseover
        particleSprite.anchor.set(0.5);                               // center anchor point
        particleSprite.blendMode = PIXI.BLEND_MODES.SCREEN;

        TweenMax.set(particleSprite, {
            pixi: {
                x: particleSettings.x,
                y: particleSettings.y,
                scale: particleSettings.scale,
                alpha: particleSettings.alpha
            }
        }, 0);

        app.stage.addChild(particleSprite);

    }

I would be grateful for any help

1 Answers1

0

I think DOM-to-Canvas using D3 and WORKING WITH D3.JS AND CANVAS: WHEN AND HOW can help you better, You can use virtual dom for d3`s data enter update.

<custom class="group" width="960" height="500">
  <custom class="circle" scale="1"></custom>
  <custom class="circle" scale="1"></custom>
  …
</custom:sketch>

The browser ignores these elements because they exist in our "custom" namespace. To render them, we use a timer that iterates over the child elements and draws them to a canvas element.

you can use d3.select('custom.group').selectAll('custom.circle').data(data),then you will have enter,eixt. like:

d3.select('canvas').on('click',function(){
   let update = d3.select('custom.group').selectAll('custom.circle').data(data);
   update.enter()...;
   update.exit()...
})

then you can use timer like:

d3.timer(function(){
   d3.selectAll('custom.circle').each(function(d){
       ...
   })
})

hope it is help for you

Fboy
  • 85
  • 10