How to create a svg canvas?

Sorry I didn’t know how to verbalize a good question in the title…

I am making a web app that is drawing a piano music score in an alternative music notation. It’s going to be a score editor.

For this editor, I want to use the SVG element to draw the score. But the following problem occurs: The svg element does weird scaling and I need some help to understand the behavior.

The svg element should have the following behavior:

  • When the drawing is bigger than the viewport, scrollbars should appear in both directions.
  • The svg element is automatically changing its size(viewBox?) based on the browser screen size.
  • When changing the browser screen size the scale of the drawing should never change.
  • position x=0 y=0 is always in the top-left corner; I’ve had weird results on particularly this one.

I made an HTML file that draws the editor staff. The draw_editor_staff(x,y,length) function is set to draw_editor_staff(0,0,400) and should appear at the top left corner but it centers the drawing and when changing the screen size it starts to scale down or up depending on the screen size. I don’t want that. The drawing should always start on the top left corner and not change in size if you have a smaller screen.
My code:

<!DOCTYPE html>

<!-- 
    PianoScript is a music notation for pianists
    who want to read music in an efficient elegant way.
    Read the docs for more information...

    This is the main PianoScript Editor app. It
    contains css, javascript and html in one file.
    I chose this because I like to write programs in
    one file and html, css and javascript are capable
    of doing that.

    The editor opens and saves MIDI-files. You can export
    the score to pdf or print directly from within the app.
 -->

<html>
    <head>
        <title>PianoScript</title>
        <style type="text/css">
            html {
                background-color: black;
            }
            #svgcanvas {
                position: fixed;
                top: 75px;
                left: 0;
                width: 100%;
                height: 100vh;
            }
            svg {
                top: 0%;
                left: 0%;
                height: 100%;
                width: 100%;
                background-color: #fffec4;
                overflow-x: auto;
            }
            h1 {
                color: white;
            }
        </style>
    </head>










    <!-- HTML elements -->
    <h1>PianoScript Editor V1.0</h1>

    <div id="svgcanvas">
        <svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 400 400"></svg>
    </div>















    <!-- js drawing functions -->
    <script type="text/javascript" id="drawing_functions">
        function draw_line(x1,y1,x2,y2,opt) {
            // this function draws basic lines on the svg element.

            // initialise optional parameters
            opt = opt                       || {};
            opt.width = opt.width           || 1;
            opt.color = opt.color           || 'black';
            opt.dash = opt.dash             || 0;
            opt.id = opt.id                 || 'default';
            opt.capstyle = opt.capstyle     || 'round';

            // drawing the line
            var svg = document.querySelector('svg');
            var newLine = document.createElementNS('http://www.w3.org/2000/svg','line');
            newLine.setAttribute('x1',x1);
            newLine.setAttribute('y1',y1);
            newLine.setAttribute('x2',x2);
            newLine.setAttribute('y2',y2);
            newLine.setAttribute('stroke-linecap', 'round')
            newLine.setAttribute('stroke-width', opt.width);
            newLine.setAttribute('stroke', opt.color);
            newLine.setAttribute('stroke-dasharray', opt.dash)
            newLine.setAttribute('id', opt.id)
            svg.appendChild(newLine);
        }
    </script>












    <!-- drawing editor staff -->
    <script type="text/javascript" id="drawing_editor_staff">
        function draw_editor_staff(x,y,length) {
            // this function draws the staff while in editing mode.
            
            var ypos = y
            
            for (var i = 0; i < 7; i++) {
                draw_line(x,ypos,x+length,ypos,{id:'staff-line'})
                draw_line(x,ypos+5,x+length,ypos+5,{id:'staff-line'})
                draw_line(x,ypos+10,x+length,ypos+10,{id:'staff-line'})

                if (i === 3) {
                    draw_line(x,ypos+20,x+length,ypos+20,{width:.5,dash:[6,4],id:'staff-line'})
                    draw_line(x,ypos+25,x+length,ypos+25,{width:.5,dash:[6,4],id:'staff-line'})
                }
                else {
                    draw_line(x,ypos+20,x+length,ypos+20,{width:.5,id:'staff-line'})
                    draw_line(x,ypos+25,x+length,ypos+25,{width:.5,id:'staff-line'})
                }

                ypos += 35
            }
            draw_line(x,ypos,x+length,ypos)
        }
        // test
        draw_editor_staff(0,0,400)
    </script>
</html>

I hope my question is clear and looking forward to learn how this works :slight_smile:

Everything in your code uses relative unites, if you don’t want for things to change, then those are not the best to use.

Thank you for your reply! But can you give an example? which element is relative and should be absolute and how? Or do you mean something else? I am literally trying to change all settings but I never get the wanted behavior.

All those are relative. If you want something that doesn’t scale you need to use non-relative units, for example px
or also rem or em which are relative to font-size so don’t change while you resize the browser, but are still responsive units

Ah, I see, thank you for giving these examples.

It doesn’t completely answer my question, I am still looking in a dark room full of possibilities. Before this project, I created a score editor in python using Tkinter. I used the Tkinter canvas and could just draw anything on it and then set the ‘bounding box’ around the drawing to be able to scroll if the drawing was bigger than the view/screen. I want to create exactly that in html/javascript/css.

How to create a svg canvas?

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.