Draw a crescent moon using SVG in HTML

五迷三道 提交于 2020-01-01 05:49:13

问题


Is it possible to draw a crescent moon using SVG in HTML? I've been trying things out at W3 Schools but I don't see an example of this. I don't need any of the shading that you see in typical google images of 'crescent moon', just a solid border crescent moon.


回答1:


Please note that my solution might not be the best. I am not an expert when it comes to vector graphics and you should definitely look for other solution

The approach I took is to draw another image with the same background. It will look like:

To Eliminate the extra border I draw another circle above it

Now Set the 3rd image border to white it will look like:

If you are not using borders you only need to use 2 circles

You might also wanna take a look at clipping and masking. It might be a better approach.

<!DOCTYPE html>
<html>
<body>

<h1>My first SVG</h1>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
   <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
   <circle cx="115" cy="50" r="30" stroke="black" stroke-width="2" fill="white" />
   <circle cx="130" cy="50" r="23" stroke="white" stroke-width="2" fill="white" />
</svg> 

</body>
</html>

Side note : W3Schools isn't really the reference you should be relying on. It's full of wrong information and outdated stuff. Better resources include:

  1. Mozilla developers network
  2. Web Platform



回答2:


Rather than drawing three circles you can draw a path with two arcs:

<path d="M50 20A40 40 0 1 0 50 70 30 30 0 1 1 50 20z" stroke="black" stroke-width="2" fill="red"/>

This reads as

M 50 20 Move to position (50, 20)

A 40 40 0 1 0 50 70 Draw an arc from that point to position (50, 70). The arc should have a radius of 40 in the x-axis and 40 in the y axis.

30 30 0 1 1 50 20 Draw another arc in the opposite direction from the current point to (50, 20) with a radius of 30 in both axes.

z Join the ends nicely

For more information see SVG specification




回答3:


Here's a JS/CSS solution that doesn't require SVG, in case it's useful to anyone:

http://codebox.org.uk/pages/html-moon-planet-phases

(disclaimer - I wrote it)




回答4:


I found the existing answers lacked the poetry of an Easter Egg, were not based on science and were not that user friendly.

Here is an icon I built for 'dark mode':

<svg id="moon" viewBox="-6 -6 12 12">
    <title>Dark mode</title>
    <defs>
        <mask id="earth">
            <rect fill="white" x="-5" y="-5" width="10" height="10"></rect>
            <circle fill="black" cx="3.141592654" r="5"/>
        </mask>
    </defs>
    <circle r="5" fill="currentColor" mask="url(#earth)" transform="rotate(-23.5)"/>
</svg>

Things to know:

  • The viewbox is centered
  • Width and height is not provided as this is a vector graphic that scales
  • Scale can be specified in CSS
  • The standard svg namespace definition is not needed in evergreen browsers
  • the mask is an offset circle, offset by pi just for to pay homage to the circle
  • the icon is tilted by 23.5 degrees as that is the tilt of the earth
  • the id tags are sensibly named, 'earth' for the mask and 'moon' for the icon
  • the fill is currentColor so that the icon is black on a white page and white on a black page
  • for brevity the origin of the circles is not given as this defaults to the centre of the viewbox, with the viewbox having a negative origin
  • if a fixed size is needed then width and height can be added
  • if used inline in a document as a clickable icon then the CSS needs to have pointer-events: bounding-box specified so that there is a click area
  • for usability you can change the <title> to be what you want
  • the viewbox includes padding, to increase it change the viewbox accordingly
  • the icon should weigh in at a lot less than 256 bytes

If Easter Eggs are morally wrong in your workplace and you can't inline your SVGs then you can save this oneliner as an image and use it that way:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="-6 -6 12 12"><defs><mask id="a"><rect width="10" height="10" x="-5" y="-5" fill="#fff"/><circle cx="3" r="5"/></mask></defs><circle r="5" fill="currentColor" mask="url(#a)" transform="rotate(-23)"/></svg>

This looks the same at icon size even though there are no floating point numbers.

If you want to use the icon inline in your CSS rather than your document (keeping presentation out of markup) then you can specify a CSS variable with the SVG content and then use that in a pseudo selector.

In your script for changing to 'dark mode' you can update the CSS variable or if you want some informative text as well then you can do the usual add a class to hide it method, e.g.::

[].map.call(document.querySelectorAll('button'), function (event) {
    event.addEventListener("click", function (event) {                       [].map.call(document.querySelectorAll('button'), function (el) {
            el.classList.toggle('hide');
        });
    });
});
:root {
                --icon-moon-dark: url('data:image/svg+xml,\
            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-6 -6 12 12"> \
                <defs> \
                    <mask id="earth"> \
                        <rect fill="white" x="-5" y="-5" width="10" height="10"></rect> \
                       <circle fill="black" cx="3.141592654" r="5"/> \
                    </mask> \
                </defs> \
                <circle r="5" fill="white" mask="url(%23earth)" transform="rotate(-23.5)"/> \
            </svg>');
            --icon-moon-light: url('data:image/svg+xml,\
            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-6 -6 12 12"> \
                <defs> \
                    <mask id="earth"> \
                        <rect fill="white" x="-5" y="-5" width="10" height="10"></rect> \
                       <circle fill="black" cx="3.141592654" r="5"/> \
                    </mask> \
                </defs> \
                <circle r="5" fill="black" mask="url(%23earth)" transform="rotate(-23.5)"/> \
            </svg>');
    }
    
    .hide {
        display: none;
    }
    nav > button {
        padding:0;
        font-size: x-large;
    }
        
    #dark-mode span {
        display: grid;
        grid-template-columns: auto 1fr;
        align-items: center;
        grid-auto-flow: column;
        text-transform: uppercase;
        font-family: fantasy;
        padding: .5em 1em;
    }

    #dark-mode span::before {
        content: var(--icon-moon-light);
        width: 1.5em;
        height: 1.5em;
    }
    #light-mode span {
        background: black;
        color: white;
        display: grid;
        grid-template-columns: auto 1fr;
        align-items: center;
        grid-auto-flow: column;
        text-transform: uppercase;
        font-family: cursive;
        padding: .5em 1em;
    }

    #light-mode span::before {
        content: var(--icon-moon-dark);
        width: 1.5em;
        height: 1.5em;
    }
<nav><button id="dark-mode" class="hide"><span>Light mode</span></button>
<button id="light-mode"><span>Dark mode</span></button><nav>



回答5:


For the records: CSS only version (no need for SVG) (updated with solid border)

http://jsfiddle.net/KA3yp/1/

HTML:

<div class="crescent"></div>

CSS:

.crescent {
    width: 300px;
    height: 300px;
    background-color: #f00;
    border-radius:150px;
    position: relative;
}

.crescent:before {
    content: "";
    width:220px;
    height: 220px;
    display: block;
    position: absolute;
    border-radius: 110px;
    right: -5px;
    top: 40px;
    background: #fff;
    border: 2px solid #000;
}

.crescent:after {
    background: none repeat scroll 0 0 #FFFFFF;
    border-radius: 100px;
    content: "";
    display: block;
    height: 140px;
    position: absolute;
    right: -18px;
    top: 83px;
    width: 140px;
}



回答6:


I use Raphael.js to draw this moon here: http://jsfiddle.net/franky85/SX3g8/

Or use the code like this:

var paper = Raphael(0, 0, "100%", "100%");
var backgroundColor = 'white';
var moonColor = 'darkorange';

var c = paper.circle(50, 50, 40).attr({
    fill: moonColor,
    'stroke-width': 0
});

var e = paper.ellipse(50, 50, 20, 40).attr({
    fill: backgroundColor,
    'stroke-width': 0
});

var r = paper.rect(50, 10, 40, 80).attr({
    fill: backgroundColor,
    'stroke-width': 0
});

var set = paper.set();
set.push(c);
set.push(e);
set.push(r);

For more complex SVG draw, you'd better use Raphael.js lib.

The document of Raphael.js is here: http://raphaeljs.com/reference.html



来源:https://stackoverflow.com/questions/16664244/draw-a-crescent-moon-using-svg-in-html

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!