简体   繁体   中英

Dynamically Resize Complex Canvas Path HTML5

I've created a drawing of a truck using paths in an HTML5 canvas. The canvas image itself is close to 900 lines of code and I've implemented a function to draw the image based on a resize ratio determined by the window's width/height. The end result is that the canvas and all elements within the canvas are dynamically resized to fit the contents of the window.

Keep in mind that I'm only on day 2 of utilizing the canvas, so I may have missed something, but there has got to be an easier way to accomplish what I am doing. So, my question is: Is there an easier way / method to accomplish resizing the canvas and its internal elements when complex paths are involved?

A sample of my code is below and only resizes on body load, I've not attached it to an onresize listener yet... I could not fit it all in so you can get the full source here:

http://www.epixseo.com/fullsource.txt

as you can see, I pass the canvasWidth into the semitruckv1 function and determine a resize ratio.... then multiply every coordinate and lineWidth with that resize ratio... which takes a while to do... (you should be able to copy+paste the full source code and run local in your IDE)

<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="UTF-8" />
  <title>Semi truck</title>
  <style type="text/css">
  body {
      margin:0px;
  }
  </style>
  <script>

    function init() {

        var viewportWidth = window.innerWidth;
        var viewportHeight = window.innerHeight;

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

        var canvasWidth = viewportWidth;
        var canvasHeight = viewportHeight;
        canvas.style.position = "fixed";
        canvas.setAttribute("width", canvasWidth);
        canvas.setAttribute("height", canvasHeight);

        var ctx = canvas.getContext("2d");

        semitruckv1(ctx, canvasWidth);
    }

    function semitruckv1(ctx, canvasWidth) {
        //347 default width of initial image

        var resizeRatio = canvasWidth/347;
      // semitruckv1/Path
      ctx.save();
      ctx.beginPath();
      ctx.moveTo(251.3*resizeRatio, 143.8*resizeRatio);
      ctx.bezierCurveTo(251.3*resizeRatio, 146.9*resizeRatio, 253.9*resizeRatio, 149.5*resizeRatio, 257.0*resizeRatio, 149.5*resizeRatio);
      ctx.bezierCurveTo(260.2*resizeRatio, 149.5*resizeRatio, 262.8*resizeRatio, 146.9*resizeRatio, 262.8*resizeRatio, 143.8*resizeRatio);
      ctx.bezierCurveTo(262.8*resizeRatio, 140.6*resizeRatio, 260.2*resizeRatio, 138.1*resizeRatio, 257.0*resizeRatio, 138.1*resizeRatio);
      ctx.bezierCurveTo(253.9*resizeRatio, 138.1*resizeRatio, 251.3*resizeRatio, 140.6*resizeRatio, 251.3*resizeRatio, 143.8*resizeRatio);
      ctx.closePath();
      ctx.strokeStyle = "rgb(1, 1, 1)";
      ctx.lineWidth = 1*resizeRatio;
      ctx.stroke();

      // semitruckv1/Path
      ctx.beginPath();
      ctx.moveTo(243.3*resizeRatio, 143.8*resizeRatio);
      ctx.bezierCurveTo(243.3*resizeRatio, 151.4*resizeRatio, 249.5*resizeRatio, 157.5*resizeRatio, 257.0*resizeRatio, 157.5*resizeRatio);
      ctx.bezierCurveTo(264.6*resizeRatio, 157.5*resizeRatio, 270.8*resizeRatio, 151.4*resizeRatio, 270.8*resizeRatio, 143.8*resizeRatio);
      ctx.bezierCurveTo(270.8*resizeRatio, 136.2*resizeRatio, 264.6*resizeRatio, 130.1*resizeRatio, 257.0*resizeRatio, 130.1*resizeRatio);
      ctx.bezierCurveTo(249.5*resizeRatio, 130.1*resizeRatio, 243.3*resizeRatio, 136.2*resizeRatio, 243.3*resizeRatio, 143.8*resizeRatio);
      ctx.closePath();
      ctx.lineWidth = 1*resizeRatio;
      ctx.stroke();

      // semitruckv1/Path
      ctx.beginPath();
      ctx.moveTo(241.3*resizeRatio, 143.8*resizeRatio);
      ctx.bezierCurveTo(241.3*resizeRatio, 152.5*resizeRatio, 248.3*resizeRatio, 159.6*resizeRatio, 257.0*resizeRatio, 159.6*resizeRatio);
      ctx.bezierCurveTo(265.7*resizeRatio, 159.6*resizeRatio, 272.8*resizeRatio, 152.5*resizeRatio, 272.8*resizeRatio, 143.8*resizeRatio);
      ctx.bezierCurveTo(272.8*resizeRatio, 135.1*resizeRatio, 265.7*resizeRatio, 128.0*resizeRatio, 257.0*resizeRatio, 128.0*resizeRatio);
      ctx.bezierCurveTo(248.3*resizeRatio, 128.0*resizeRatio, 241.3*resizeRatio, 135.1*resizeRatio, 241.3*resizeRatio, 143.8*resizeRatio);
      ctx.closePath();
      ctx.lineWidth = 0.3*resizeRatio;
      ctx.stroke();

      // semitruckv1/Path
      ctx.beginPath();
      ctx.moveTo(232.5*resizeRatio, 143.8*resizeRatio);
      ctx.bezierCurveTo(232.5*resizeRatio, 157.3*resizeRatio, 243.5*resizeRatio, 168.3*resizeRatio, 257.0*resizeRatio, 168.3*resizeRatio);
      ctx.bezierCurveTo(270.6*resizeRatio, 168.3*resizeRatio, 281.6*resizeRatio, 157.3*resizeRatio, 281.6*resizeRatio, 143.8*resizeRatio);
      ctx.bezierCurveTo(281.6*resizeRatio, 130.2*resizeRatio, 270.6*resizeRatio, 119.3*resizeRatio, 257.0*resizeRatio, 119.3*resizeRatio);
      ctx.bezierCurveTo(243.5*resizeRatio, 119.3*resizeRatio, 232.5*resizeRatio, 130.2*resizeRatio, 232.5*resizeRatio, 143.8*resizeRatio);
      ctx.closePath();
      ctx.lineWidth = 0.5*resizeRatio;
      ctx.stroke();

      //THERE ARE ABOUT ANOTHER 800 LINES OF PATH DRAWING DOWNLOAD THE FULL SOURCE TO VIEW: www.epixseo.com/fullsource.txt

    }
  </script>
 </head>
 <body onLoad="init()">
   <canvas id="canvas"></canvas>
 </body>
</html>

画布上下文具有scale功能,可以自动缩放画布上绘制的任何内容,直到上下文恢复为止,或者将缩放比例更改为1.请参阅https://developer.mozilla.org/en-US/docs/网络/指南/ HTML / Canvas_tutorial /转换#A_scale_example

the best way to handle this depends on your future applications for example:

  1. If you are just drawing the same truck but want to redraw when the page is resized instead use toDataURL method of the canvas to pull the image of the canvas then resize the canvas (using .width and .height instead of css because you will stretch the image) then use the drawImage method to draw that data url back to the canvas (or just plop it into an img tag).
  2. If you plan to animate a piece of the truck, the wheels for example, you should use the same strategy as step one however instead of pulling an image of the truck pull only pieces. For example if you are animating the wheels: Pull an image of the main body of the truck then pull an image of just a wheel, then draw the truck once at resize, but then continuously redraw the wheels rotating them slightly every frame.

我不太了解使用canvas(我有GameMaker:HTML5为我做),但你不能只加载一个SVG图像并以适当的大小绘制它吗?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM