I want to draw pattern on an image with canvas on click

365 views Asked by At

i want to draw pattern on a image with canvas on click you can understand more with the provided images here is what end result i want https://i.stack.imgur.com/tHLY0.png But i am having this blurred line https://i.stack.imgur.com/6AZVI.png

i am using following code

(
    function() {
        var canvas = document.querySelector('#canvas');
        var ctx = canvas.getContext('2d');

        var sketch = document.querySelector('#sketch');
        var sketch_style = getComputedStyle(sketch);
        canvas.width = parseInt(sketch_style.getPropertyValue('width'));
        canvas.height = parseInt(sketch_style.getPropertyValue('height'));

        var mouse = {x: 0, y: 0};
        var last_mouse = {x: 0, y: 0};

        /* Mouse Capturing Work */
        canvas.addEventListener('mousemove', function(e) {
            last_mouse.x = mouse.x;
            last_mouse.y = mouse.y;

            mouse.x = e.pageX - this.offsetLeft;
            mouse.y = e.pageY - this.offsetTop;
        }, false);


        var texture = document.getElementById("texture");

        pFill = ctx.createPattern(texture, "repeat");

        ctx.strokeStyle = pFill;

        /* Drawing on Paint App */
        ctx.lineWidth = 12;
        ctx.lineJoin = 'square';
        ctx.lineCap = 'square';
        canvas.addEventListener('mousedown', function(e) {
        canvas.addEventListener('mousemove', onPaint, false);
        }, false);

        canvas.addEventListener('mouseup', function() {
        canvas.removeEventListener('mousemove', onPaint, false);
        }, false);

        var onPaint = function() {
            ctx.beginPath();
            ctx.moveTo(last_mouse.x, last_mouse.y);
            ctx.lineTo(mouse.x, mouse.y);

            ctx.closePath();
            ctx.stroke();
        };
    }()
);

$( document ).ready(function() {
    var c = document.getElementById("canvas");
    var ctx = c.getContext("2d");
    var img = document.getElementById("scream");
    ctx.drawImage(img,10,10);
});
1

There are 1 answers

3
Kirill Slatin On BEST ANSWER

Method with stroke pattern will not work here. Because this pattern position is fixed. So when your line is not exactly horizontal or vertical you will have a distorted image instead of a chain of accurate balls.

Well I think the whole approach should be reconsidered.

User should create a path like in photoshop, which is visible as a temporary line. At first it can easily be a polyline, where vertices are pointed by clicks. And when the path is confirmed (by double click for example) you should remove the temporary line and put the balls along the path with a given step. In this case you can handle all turns and regularity distortions.

This is quite a bunch of work, but the task is in reality much more complex than it seems to be.

As a quick workaround you can try a simple approach. Drop a ball each time distance from the previous drop is more than double radius (for example) of the ball..

var lastBall = {x: null, y : null};
function drawBall(center){
      ctx.beginPath();
      ctx.arc(center.x, center.y, 10, 0, 2 * Math.PI, false);
      ctx.fillStyle = 'orange';
      ctx.fill();
}
function distance(a,  b){
    return Math.sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
}
var onPaint = function() {
    if(!lastBall.x || distance(lastBall, mouse) > 25 ){
        drawBall(mouse);
        lastBall.x = mouse.x;
        lastBall.y = mouse.y;
    }

The code is rough you should define proper variables for color and radius, or perhaps replace it with your pattern, but you can get the idea

Fiddle