How do I create a teardrop in HTML?

后端 未结 12 545
生来不讨喜
生来不讨喜 2020-12-02 03:59

How do I create a shape like this to display on a webpage?

I don\'t want to use images since they would get blurry on scaling

12条回答
  •  执念已碎
    2020-12-02 04:21

    HTML Canvas

    This is an option uncovered in this thread so far. The commands used for Canvas drawings are very similar to SVG (and web-tiki deserves the credits for the base idea used in this answer).

    The shape in question can be created either using canvas' own curve commands (Quadratic or Bezier) or the Path API. The answer contains examples for all three methods.

    The browser support for Canvas is quite good.


    Using Quadratic Curves

    window.onload = function() {
      var canvas = document.getElementById('canvas');
      if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
    
        ctx.beginPath();
        ctx.lineJoin = 'miter';
        ctx.moveTo(120, 20);
        ctx.quadraticCurveTo(117.5, 30, 148, 68);
        ctx.arc(120, 88, 34.5, 5.75, 3.66, false);
        ctx.quadraticCurveTo(117.5, 35, 120, 20);
        ctx.closePath();
        ctx.strokeStyle = '#000';
        ctx.lineWidth = 2;
        ctx.fillStyle = '#77CCEE'
        ctx.stroke();
        ctx.fill();
      }
    }
    canvas {
      margin: 50px;
      height: 100px;
      width: 200px;
      transform: scale(1.5);
    }
    
    body{
      background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
    }

    Below is an advanced version with gradient fill and shadows. I have also included a hover effect on the shape to illustrate one drawback of Canvas when compared to SVG. Canvas is raster (pixel) based and hence would look blurred/pixelated when scaled beyond a certain point. The only solution to that would be to repaint the shape on every browser resize which is an overhead.

    window.onload = function() {
      var canvas = document.getElementById('canvas');
      if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
        var lineargradient = ctx.createRadialGradient(135, 95, 1, 135, 95, 10);
        lineargradient.addColorStop(0, 'white');
        lineargradient.addColorStop(1, '#77CCEE');      
        ctx.beginPath();
        ctx.lineJoin = 'miter';
        ctx.moveTo(120, 20);
        ctx.quadraticCurveTo(117.5, 30, 148, 68);
        ctx.arc(120, 88, 34.5, 5.75, 3.66, false);
        ctx.quadraticCurveTo(117.5, 35, 120, 20);
        ctx.closePath();
        ctx.strokeStyle = '#333';
        ctx.lineWidth = 3;
        ctx.fillStyle = lineargradient;
        ctx.shadowOffsetX = 2;
        ctx.shadowOffsetY = 2;
        ctx.shadowBlur = 2;
        ctx.shadowColor = "rgba(50, 50, 50, 0.5)";      
        ctx.stroke();
        ctx.fill();
      }
    }
    canvas {
      margin: 50px;
      height: 100px;
      width: 200px;
      transform: scale(1.5);
    }
    
    
    /* Just for demo */
    
    body{
      background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
    }
    
    canvas{
      transition: all 1s;
    }
    
    canvas:hover{
      transform: scale(2);
    }


    Using Bezier Curves

    window.onload = function() {
      var canvas = document.getElementById('canvas');
      if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
        var lineargradient = ctx.createRadialGradient(135, 95, 1, 135, 95, 10);
        lineargradient.addColorStop(0, 'white');
        lineargradient.addColorStop(1, '#77CCEE');
        ctx.beginPath();
        ctx.lineJoin = 'miter';
        ctx.arc(120, 88, 35, 5.74, 3.66, false);
        ctx.bezierCurveTo(100, 55, 122, 27.5, 120, 20);
        ctx.bezierCurveTo(122, 27.5, 121, 31.5, 150, 70);
        ctx.closePath();
        ctx.strokeStyle = 'rgba(109,195,250,0.2)';
        ctx.lineWidth = 1;
        ctx.fillStyle = lineargradient;
        ctx.shadowOffsetX = 2;
        ctx.shadowOffsetY = 2;
        ctx.shadowBlur = 2;
        ctx.shadowColor = "rgba(50, 50, 50, 0.5)";
        ctx.stroke();
        ctx.fill();
      }
    }
    canvas {
      margin: 75px;
      height: 300px;
      width: 300px;
      transform: scale(1.5);
    }
    body {
      background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
    }

    Using Path API

    window.onload = function() {
      var canvas = document.getElementById('canvas');
      if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
    
        ctx.lineJoin = 'miter';
        var p = new Path2D("M120 20 Q117.5 30 146 68 A34 34 0 1 1 92 68 Q117.5 35 120 20z");
        ctx.strokeStyle = '#000';
        ctx.lineWidth = 2;
        ctx.fillStyle = '#77CCEE'
        ctx.stroke(p);
        ctx.fill(p);
      }
    }
    canvas {
      margin: 50px;
      height: 100px;
      width: 200px;
      transform: scale(1.5);
    }
    
    body {
      background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
    }

    Note: As mentioned in my answere here, the Path API is not yet supported by IE and Safari.


    Further reading:

    • 7 Reasons to Consider SVGs Instead of Canvas
    • HTML5 Canvas vs. SVG: Choose the Best Tool for the Job
    • What is the difference between SVG and HTML5 Canvas?

提交回复
热议问题