简体   繁体   English

对HTML5画布元素进行动画处理以更改形状(滚动或翻转时),它们之间没有间隙(这些元素必须垂直连接)

[英]Animate HTML5 canvas elements to change shape (on scroll or rollover) without gaps between them (the elements must be vertically connected)

How can I modify the shape of all elements (one by one) while scrolling on canvas or by rollover each element (to get random shape, but with some boundaries for the text to be in section more/less) and also to keep the elements vertically connected together? 我如何在画布上滚动或将每个元素翻转时修改所有元素的形状(一个一个地变)(以获取随机形状,但要使文本在部分中具有更多/更少的边界),并且还要保留这些元素垂直连接在一起? (no gaps in between to follow each other). (彼此之间没有差距)。 I guess this can be done with coordinates? 我猜这可以用坐标来完成吗?

Screenshot 截图

I've done some research and I haven't found a similar example. 我已经做了一些研究,但没有找到类似的例子。 I am open also to other solutions, javascript libraries, SCSS, skew() CSS function , clip-path CSS property , SVG or mask or anything else for the web (I mean, there is no special reason to use only one specific way). 我也对其他解决方案,JavaScript库,SCSS, skew()CSS函数剪切路径CSS属性 ,SVG或mask或其他用于Web的网站持开放态度(我的意思是,没有特别的理由只使用一种特定的方式) 。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <style type="text/css">
    #myCanvas {
      border: 1px solid black;
      width: 100%;
      height: auto;
    }
  </style>
  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
</head>
<body>

    <canvas id="myCanvas"></canvas>

    <script>
    $(function() {

        var canvas = document.getElementById('myCanvas'),
        width = window.innerWidth,
        height = window.innerHeight,
        elemWidth = window.innerWidth - 20,
        lineheight = 30,
        txt1 = 'Lorem 1 ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula\neget dolor. Aenean massa. Cum sociis natoque penatibus et',
        txt2 = 'Lorem 2 ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula\neget dolor. Aenean massa. Cum sociis natoque penatibus et',
        txt3 = 'Lorem 3 ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula\neget dolor. Aenean massa. Cum sociis natoque penatibus et',
        lines1 = txt1.split('\n'),
        lines2 = txt2.split('\n'),
        lines3 = txt3.split('\n');

        window.addEventListener('resize', resizeCanvas, false);

        function resizeCanvas() {
            canvas.width = width;
            canvas.height = height;
            drawStuff();
        }

        resizeCanvas();

        function drawStuff() {

            // element 1
            var poly1 = [5,100, (elemWidth-100),5, elemWidth,400, 5,300 ];
            var ctx1 = canvas.getContext('2d');
            ctx1.fillStyle = '#ff8080';
            ctx1.beginPath();
            ctx1.moveTo(poly1[0], poly1[1]);
            for(item = 2 ; item < poly1.length - 1 ; item += 2) {
                ctx1.lineTo(poly1[item], poly1[item + 1]);
            }
            ctx1.closePath();
            ctx1.fill();
            ctx1.fillStyle = "Black";
            ctx1.font = '70px Arial';
            ctx1.fillText("Some title 1",300,180);
            ctx1.font = '30px Arial';
            for (var i = 0; i<lines1.length; i++) {
                ctx1.fillText(lines1[i], 300, 220 + (i*lineheight) );
            }

            // element 2
            var poly2 = [5,300, elemWidth,400, (elemWidth-100),800, 50,600];
            var ctx2 = canvas.getContext('2d');
            ctx2.fillStyle = '#e9afaf';
            ctx2.beginPath();
            ctx2.moveTo(poly2[0], poly2[1]);
            for(item = 2 ; item < poly2.length - 1 ; item += 2) {
                ctx2.lineTo(poly2[item], poly2[item + 1]);
            }
            ctx2.closePath();
            ctx2.fill();
            ctx2.fillStyle = "Black";
            ctx2.font = '70px Arial';
            ctx2.fillText("Some title 2",300,480);
            ctx2.font = '30px Arial';
            for (var i = 0; i<lines2.length; i++) {
                ctx2.fillText(lines2[i], 300, 520 + (i*lineheight) );
            }

            // element 3
            var poly3 = [50,600, (elemWidth-100),800, elemWidth,940, 5,900];
            var ctx3 = canvas.getContext('2d');
            ctx3.fillStyle = '#c8b7b7';
            ctx3.beginPath();
            ctx3.moveTo(poly3[0], poly3[1]);
            for(item = 2 ; item < poly3.length - 1 ; item += 2) {
                ctx3.lineTo(poly3[item], poly3[item + 1]);
            }
            ctx3.closePath();
            ctx3.fill();
            ctx3.fillStyle = "Black";
            ctx3.font = '70px Arial';
            ctx3.fillText("Some title 3",300,780);
            ctx3.font = '30px Arial';
            for (var i = 0; i<lines3.length; i++) {
                ctx3.fillText(lines3[i], 300, 820 + (i*lineheight) );
            }

        }

    });
    </script>
</body>
</html>

Update: I've created the suggested SVGs, since my target is the animation, any suggestions/ideas on updating those polygon points values (for example on rollover, I can use jquery) that the next polygons can follow (update points) dynamically and also staying connected? 更新:我创建了建议的SVG,因为我的目标是动画,所以有关更新这些多边形点值的任何建议/想法(例如,在翻转时,我可以使用jquery),下一个多边形可以动态跟随(更新点),还保持联系?

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<style type="text/css">
  svg {
    width: 100%;
    height: auto;
  }
</style>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
</head>
<body>
<svg width="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
  <polygon fill="#99bde5" points="0,5 95,0 100,35, 0,20" id="testElem"/>
  <text x="10" y="12" text-anchor="left" fill="black" font-size="6">Some title 1</text>
  <text x="10" y="15" text-anchor="left" fill="black" font-size="3">
      <tspan>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</tspan>
      <tspan x="10" dy="3">Aenean commodo ligula eget dolor. Aenean massa.</tspan>
  </text>

  <polygon fill="#c9e599" points="0,20 100,35 100,55, 5,50" id="testElem"/>
  <text x="10" y="36" text-anchor="left" fill="black" font-size="6">Some title 1</text>
  <text x="10" y="40" text-anchor="left" fill="black" font-size="3">
      <tspan>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</tspan>
      <tspan x="10" dy="3">Aenean commodo ligula eget dolor. Aenean massa.</tspan>
  </text>

  <polygon fill="#a5e599" points="5,50 100,55 94,75, 5,80" id="testElem"/>
  <text x="10" y="63" text-anchor="left" fill="black" font-size="6">Some title 1</text>
  <text x="10" y="67" text-anchor="left" fill="black" font-size="3">
      <tspan>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</tspan>
      <tspan x="10" dy="3">Aenean commodo ligula eget dolor. Aenean massa.</tspan>
  </text>

  <polygon fill="#99e5ca" points="5,80 94,74 100,100, 0,100" id="testElem"/>
  <text x="10" y="89" text-anchor="left" fill="black" font-size="6">Some title 1</text>
  <text x="10" y="92" text-anchor="left" fill="black" font-size="3">
      <tspan>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</tspan>
      <tspan x="10" dy="3">Aenean commodo ligula eget dolor. Aenean massa.</tspan>
  </text>
</svg>
</body>
</html>

PS. PS。 The SVG points are x,y and clock-wise starting from top-left to bottom-left. SVG点是x,y,从左上角到左下角是顺时针方向。

I think your best bet is going to be with an svg . 我认为最好的选择是svg Here's an example of someone doing something pretty similar: https://codepen.io/erikdkennedy/pen/ygpwZg 这是某人做类似事情的示例: https : //codepen.io/erikdkennedy/pen/ygpwZg

The key is the points of the polygon added within the svg which creates a triangular section added to the rectangular header. 关键是在svg中添加的polygon的点,该点创建添加到矩形标题的三角形截面。 The svg here has no background so it's actually cutting a section out of the the header. 此处的svg没有背景,因此实际上是从标头中切出一部分。 This is basically removing a section from the parent element. 这基本上是从父元素中删除一个部分。 You can change it to div instead of header or whatever element you need it to be. 您可以将其更改为div而不是header或您需要的任何元素。

<polygon fill="white" points="0,100 100,0 100,100"/>

From the documentation , points are pairs of (x,y) coordinates. 根据文档points是(x,y)坐标对。 SVGs are very flexible and open to whatever customization you need. SVG非常灵活,可以根据需要进行任何自定义。 Setting up the points will be the only tricky part as you'll have to experiment till you get the shape(s) you need. 设置点将是唯一棘手的部分,因为您必须进行实验,直到获得所需的形状为止。 You'll need your parent elements to be large enough that you can cut sections out to fit your design. 您需要您的父元素足够大,以便可以切出适合您的设计的部分。

Update 更新

I haven't seen it confirmed in documentation, but the points appear to be percentages of the space provided. 我在文档中没有看到它的确认,但是要点似乎是所提供空间的百分比。 And, for some reason, y is flipped. 并且,由于某些原因, y被翻转。 So using that last example, 0,100 100,0 100,100 translates to bottom left, upper right, bottom right. 因此,使用最后一个示例, 0,100 100,0 100,100转换为左下,右上,右下。

Update (animation) 更新(动画)

As far as animating your points, here's another helpful example on that. 至于使您的观点生气勃勃,这是另一个有用的例子 This boils down to creating an animate tag within the svg with an ID to reference, ( documentation here ). 这归结为在svg内创建一个带有参考ID的animate标签(请参见此处的文档 )。 You set your animation properties on the animate tag. 您可以在animate标签上设置动画属性。 To trigger it call the id of the reference and then trigger it with beginElement : 要触发它,请调用引用的id ,然后使用beginElement触发它:

var animationToStar = document.getElementById("animation-to-star")
animationToStar.beginElement();

Note that the properties for to on the animate tag. 请注意, animate标签上的to属性。 This dictates what the shape should be at the end of the animation. 这决定了动画结束时的形状。 For your use case you'll want to set up event listeners for mouseover , mouseleave , and scroll to fire off the animations per your design. 对于您的用例,您将需要为mouseovermouseleave设置事件监听器,并scroll以根据设计触发动画。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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