Search code examples
colorskineticjspixel

Is it possible to change color of one pixel inside rectangle created with KineticJS?


This is my code:

var Editor = {
    layer: new Kinetic.Layer(),
    map: null,
    init: function () {
        var stage = new Kinetic.Stage({
            container: 'board',
            width: 800,
            height: 800
        })
        this.map = new Kinetic.Shape({
            sceneFunc: function(context) {
                context.beginPath();
                context.moveTo(0, 0);
                context.lineTo(mapWidth, 0);
                context.lineTo(mapWidth, mapHeight);
                context.lineTo(0, mapHeight);
                context.closePath();
                context.fillStrokeShape(this);
            },
            x: 0,
            y: 0,
            fill: 'green',
            draggable: true
        })

        this.layer.add(this.map)
        stage.add(this.layer)
    }
}

I want to change the colors of the pixels in the rectangle. Colors of pixels will be generated by the "diamond-square" algorithm. Is it possible to change the colors of individual pixels? If so, how can I do this?


Solution

  • [ Changed answer ]

    Use an offscreen html canvas to overlay the pixels in your "diamond-square" algorithm.

    Demo: http://jsfiddle.net/m1erickson/6mDSm/

    enter image description here

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Prototype</title>
        <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
        <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>
    <style>
    body{padding:20px;}
    #container{
      border:solid 1px #ccc;
      margin-top: 10px;
      width:350px;
      height:350px;
    }
    </style>        
    <script>
    $(function(){
    
    
        var stage = new Kinetic.Stage({
            container: 'container',
            width: 350,
            height: 350
        });
        var layer = new Kinetic.Layer();
        stage.add(layer);
    
        var mapWidth=50;
        var mapHeight=75;
    
        // use an offscreen canvas as a pixel-map overlaying the green map
        var pixelCanvas=document.createElement("canvas");
        var ctx=pixelCanvas.getContext("2d");
        pixelCanvas.width=mapWidth;
        pixelCanvas.height=mapHeight;
        pixelCanvas.pixels=[]
        pixelCanvas.setPixel=function(x,y,color){
            ctx.fillStyle=color;
            ctx.fillRect(x,y,1,1);
        };
    
        // create a group
        // that holds the green map background and pixel-map overlay
        var mapGroup=new Kinetic.Group({
            x:30,
            y:30,
            width:mapWidth,
            height:mapHeight,
            draggable:true
        });
        layer.add(mapGroup);
    
        // the green background
        var map=new Kinetic.Rect({
            x:0,
            y:0,
            width:mapWidth,
            height:mapHeight,
            fill:"green"
        });
        mapGroup.add(map);
    
        // an image overlay that 
        // gets "live-updates" from an offscreen canvas
    
        var pixels=new Kinetic.Image({
            x:0,
            y:0,
            image:pixelCanvas
        });
        mapGroup.add(pixels);
    
        layer.draw();
    
        // testing
    
        var y=15;
        $("#add").click(function(){
            for(var i=0;i<5;i++){
                pixelCanvas.setPixel(15,y,"red");
                pixelCanvas.setPixel(25,y,"gold");
                pixelCanvas.setPixel(35,y++,"blue");
            }
            pixels.draw();
        });
    
    
    }); // end $(function(){});
    
    </script>       
    </head>
    <body>
        <button id="add">Add test Pixels</button>
        <div id="container"></div>
    </body>
    </html>
    

    Note: my previous answer using Kinetic.Shape was leaving an undesirable "ghost"