PaperJS seems to be working correctly in file, but won't display

313 views
Skip to first unread message

PaperJSnewProgrammer

unread,
Mar 12, 2022, 12:09:17 PM3/12/22
to Paper.js
I'm just starting work on a bit of a vector "paint program". That has some various tools that one can select. I found some methods to do this in a Stack Overflow post. The original post has two placeholder tools and I added another. The two native tools work fine and display, my third tool (which runs fine as a stand along file) seems be working, does not throw errors in the browser, and from inspecting the results seems to have data in the structures. However the third too won't display. 

I realize the syntax is different in different section of the code. Both syntaxes seem to work fine, so that is not the issue. I banged on this for a long time with no joy. I'm sure it will turn out to be something simple.

Thanks in advance for any programmer eyes on this code.
Paul

<!-- Multiple Tools Paper Example -->

<!DOCTYPE html>
<html>
<style>
        html,
        body,
        canvas {
          width: 100%;
          height: 100%;
          margin: 0;
        }
</style>
<script>
        window.onload = () => {
          // Setup Paper
       
          paper.setup(document.querySelector('canvas'))
       
          // Toolstack
       
          class ToolStack {
            constructor(tools) {
              this.tools = tools.map(tool => tool())
            }
       
            activateTool(name) {
              const tool = this.tools.find(tool => tool.name === name)
              tool.activate()
            }
           
           
       
            // add more methods here as you see fit ...
          }
       
          // Tool Path, draws paths on mouse-drag
       
          const toolPath = () => {
            const tool = new paper.Tool()
            tool.name = 'toolPath'
       
            let path
           
       
            tool.onMouseDown = function(event) {
              path = new paper.Path()
              path.strokeColor = '#4242ff'
              path.strokeWidth = 15;
              path.add(event.point)
            }
       
            tool.onMouseDrag = function(event) {
              path.add(event.point)
              console.log(path);
            }
       
            return tool
          }
       
          // Tool Circle, draws a 30px circle on mousedown
       
          const toolCircle = () => {
            const tool = new paper.Tool()
            tool.name = 'toolCircle'
       
           
       
            let path
       
            tool.onMouseDown = function(event) {
              path = new paper.Path.Circle({
                center: event.point,
                radius: 30,
                fillColor: '#9C27B0'
              })
            }
       
            return tool
          }
         
         
          // This is the tool I added which does not display
          const multiLine = () => {
            const tool = new paper.Tool()
            tool.name = 'multiLine'
         
            var values = {
                        //lines: 5,
                        lines: 4,
                        //size: 40,
                        size: 10,
                        smooth: true
                    };        
           
        var paths;    
       
       
//          tool.onMouseDown = function(event) {   // this worked for debugging the tool
//               path = new paper.Path()              
//                path.strokeColor = '#ff4242'
//                path.strokeWidth = 10  
//               path.add(event.point)
//             }
//        
//     tool.onMouseDrag = function(event) {
//               path.add(event.point)
//              }
         
         
            tool.onMouseDown = function(event) {
                        paths = [];
                        for (var i = 0; i < values.lines; i++){
                            var path = new paper.Path();
                            path.strokeColor = '#FF2222';
                            path.strokeWidth = 25;
                            paths.push(path);
                            console.log(i);
                        }
                    }
                                               
       tool.onMouseDrag = function(event){
                     
                        var offset = event.delta;
                        offset.angle = offset.angle + 90;
                       
                        var lineSize = values.size / values.lines;
                        for (var i = 0; i < values.lines; i++) {
                            var path = paths[values.lines - 1 - i];
                            //offset.length = lineSize * i + lineSize / 2;
                           
                            offset.length = (-i * lineSize)  * (Math.max(event.delta.length /15, 1));
                            path.add(event.middlePoint + offset);
                           // path.smooth();
                            console.log(paths[1]);
                        }
                    }
            return tool
            }        
                   
         
       
       
          // Construct a Toolstack, passing your Tools
       
          const toolStack = new ToolStack([toolPath, toolCircle, multiLine])
       
          // Activate a certain Tool
       
          toolStack.activateTool('toolPath')
       
          // Attach click handlers for Tool activation on all
          // DOM buttons with class '.tool-button'
       
          document.querySelectorAll('.tool-button').forEach(toolBtn => {
            toolBtn.addEventListener('click', e => {
              toolStack.activateTool(e.target.getAttribute('data-tool-name'))
            })
          })
        }
       
        //       function onKeyDown(event) {
//                                 if (event.key == 'd'){
//                                     project.activeLayer.removeChildren();
//                                 }
//                                 if (event.key == 'z'){
//                                     project.activeLayer.removeChildren(project.activeLayer.lastChild.index);
//                                 }
//        
//                             }
</script>
<head>
<title>
StackExchange Multiple Tools
</title>
<meta name="generator" content="BBEdit 14.1" />
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.11.5/paper-core.js">
</script>
<button class="tool-button" data-tool-name="toolPath">
Draw Paths
</button>
<button class="tool-button" data-tool-name="toolCircle">
Stamp Circles
</button>
<button class="tool-button" data-tool-name="multiLine">
Multi Lines
</button>
<canvas resize>
</canvas>
</body>
</html>



Richard JE Cooke

unread,
May 31, 2022, 5:07:39 PM5/31/22
to Paper.js
Please don't ask for help without giving us neat code, it's a bit rude. You need to remove the tools that work, delete the commented out parts, indent consistently, add semicolons, use let and const consistently.

Anyway, your faulty tool is creating a path with no position, shape, or details.
Replace  var path = new paper.Path();   with      let path = new paper.Path.Circle(new paper.Point(200, 200), 30);    and you'll see it draws fine.

PaperJSnewProgrammer

unread,
Jun 1, 2022, 9:57:22 AM6/1/22
to Paper.js
Sorry, I'll try and be better about the code examples in the future. I was just getting going and wondering why things were so frustrating.
The paper examples all work so brilliantly but once you start coding in a javascript environment, it's a bit more confusing. There is a whole page on the paper.js site about using paper with javascript but not much in the way of examples I think.

Richard JE Cooke

unread,
Jun 1, 2022, 10:47:21 AM6/1/22
to Paper.js
Yeah, it takes a while. And the docs' whole 'paperscope' thing is stupid.  I would just ignore the examples and use the reference document.

Here's my template for new projects if it helps:

<!DOCTYPE html>
<html lang="en">


<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Style -->
    <style>
        body
        {
            padding: 0;
            margin: 0;
            background-color: black;
        }
        canvas
        {
            background-color: darkgrey;
        }
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.15/paper-full.js" integrity="sha512-XV5MGZ7Tv+G60rzU8P7tPUlaf0yz7SJ/uI9CLAwyLcZKl9kzxJQFs3nsBNZVNVAwNOkBLqrzMvjGMEycDccqiA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.js" integrity="sha512-O6tq+fkhkfCEulJBqTOZ7dsNIA98zy+GTrDmoh5aJL4Wpi8BIcg+cAW5Cfj4cdqtDmLp/5j398Z6BPpjaYjLmQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script>

//---------------------------------------------------------------------------------------------
// SETUP FUNCTIONS
//---------------------------------------------------------------------------------------------
'use strict';
window.onload = setup;
let p = null; // an alias for the paper.js global object.
let canvasWidth, canvasHeight = null;
let em = null; // relative width unit the drawing is based on

function setup()
{
    p = paper;
    const canvas = document.getElementById('canvasId');
    canvasWidth = parseInt(document.getElementById('canvasId').attributes.width.nodeValue);
    canvasHeight = parseInt(document.getElementById('canvasId').attributes.height.nodeValue);
    em = canvasWidth / 100;
    p.setup(canvas);
    drawPicture();
}

function drawPicture()
{
 // DRAW HERE
}

// HELPER FUNCTIONS ----------------------------------------

function rasterRemove(path)
{
    path.rasterize({resolution: 300});
    path.remove();
}

function exportSVGToConsole()
{
    console.log(p.project.exportSVG({asString: true}));
}

function map(value, startMin, startMax, endMin, endMax)
{
    return ((value - startMin) / (startMax - startMin)) * endMax + endMin;
}

function hsb(hue = 360, saturation = 1, brightness = 0.5, alpha = 1)
{
    return new p.Color({hue: hue, saturation: saturation, brightness: brightness, alpha: alpha});
}

function mixColors(color1, color2)
{
    return hsb( color1.hue + color2.hue / 2,
                color1.saturation + color2.saturation / 2,
                color1.brightness + color2.brightness / 2,
                color1.alpha + color2.alpha / 2);
}

function randomiseColor(color, hue = 0, saturation = 0, brightness = 0, alpha = 0) //360 for hue, all others 0-1
{
    const result = color.clone();
    result.hue = ( randomPN() * hue + result.hue) % 360;
    result.saturation = clamp( randomPN() * saturation + result.saturation, 0, 1);
    result.brightness = clamp( randomPN() * brightness + result.brightness, 0, 1);
    result.alpha = clamp( randomPN() * alpha + result.alpha, 0, 1);
    return result;
}

const clamp = (num, min, max) => Math.min(Math.max(num, min), max);

function randomPN() //returns -1 to 1
{
    return Math.random() > 0.5 ?  Math.random() : Math.random() * -1;
}

function randomGaussian() // returns value from -1 to 1 centered around zero  - https://stackoverflow.com/questions/25582882/javascript-math-random-normal-distribution-gaussian-bell-curve
{
    let u = 0, v = 0;
    while(u === 0) u = Math.random();
    while(v === 0) v = Math.random();
    let result = -4;
    while (result < -3 || result > 3) // 99.5% samples within three s.d.
    {
        u = Math.random();
        v = Math.random();
        result = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
    }
    return result / 3;
}

function randomPositiveGaussian() // returns value from 0 to 1 centered around 0.5
{
    return (randomGaussian() + 1) / 2;
}

    </script>
</head>

<body>
    <!-- A1 measures 841 x 594 mm (landscape) or 9933 x 7016 px  (1682 x 1188)-->
    <!-- <canvas id="canvasId" width="1682" height="1188"></canvas> -->

    <canvas id="canvasId" width="1500" height="750"></canvas>
</main>
</body>
</html>
Reply all
Reply to author
Forward
0 new messages