CANVAS - line with 100% of width - html

I would like to draw a line using CANVAS with 100% width acrossing through the entire screen similar to a css in the 'image-background' of the body like this example below:
Ex:
Made with CSS
body {
background-image: url(horizontal-line.png);
background-repeat: repeat-x;
background-position: 0px 10%;
}
made with CANVAS
???
How can I solve it? Thank you

Updated demo:
https://jsfiddle.net/mulperi/xnob50yd/1/
A full window sized canvas and 100% stroke in the middle of the screen
Here are the css and js parts:
<style>
canvas {
padding: 0;
margin: auto;
width: 100%;
height: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>
<canvas id="canvas"></canvas>
<script>
const c = document.getElementById("canvas");
const ctx = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
ctx.fillStyle = "red";
ctx.fillRect(0, window.innerHeight / 2, window.innerWidth, 10);
ctx.fill();
window.onresize = function() {
ctx.width = window.innerWidth;
ctx.height = window.innerHeight;
}
</script>
With window.onresize you make sure that canvas changes size dynamically with the browser window.

Canvas &lthr&gt line
Used javascript to find the width of the screen. document.documentElement.clientWidth
Then used that to set the size of the canvas element. canvas.width = screenWidth;
Then draw a rect width size 2px height and its width equal to screenWidth.
ctx.fillRect(0, 10, screenWidth, 2)
What is the 10 for? In this example i set the canvas to 20 height. So the middle of the canvas is 10.
document.addEventListener("DOMContentLoaded", function() {
draw();
});
function draw() {
var canvas = document.getElementById('demo');
//Set the canvas to viewport size
var screenWidth = document.documentElement.clientWidth;
canvas.width = screenWidth;
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgb(255, 100, 0)';
ctx.fillRect(0, 10, screenWidth, 2);
} else {
convas.addChild("No canvas here");
}
}
body {
margin: 0;
}
/*to make the canvas visible*/
#demo {
border-top: 1px solid black;
border-bottom: 1px solid black;
}
<p>Canvas</p>
<canvas id="demo" width="" height="20"></canvas>

Related

How to use WebGL to render a button background?

Let's say that I have a GL shader I'd want to use as an HTML button background (it's a pretty animated gradient). How can I achieve that?
I can think of setting the background to a texture and rendering the shader to this texture. Is that fundamentally possible?
Using a canvas inside a button is the most logical way to go, note that this is just an example and not a shader, but we use the canvas to render WebGL so it can be slightly different for your case.
var c = document.getElementsByTagName("canvas")[0];
var ctx = c.getContext("2d");
// Create gradient
var grd = ctx.createLinearGradient(0, 0, 200, 0);
grd.addColorStop(0, "red");
grd.addColorStop(1, "green");
// Fill with gradient
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 400, 200);
button {
position: relative;
background-color: transparent;
border: none;
outline: none;
padding: 8px;
}
button > div {
position: relative;
z-index: 1;
}
canvas {
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
z-index: -1;
pointer-events: none;
}
<button>
<canvas></canvas>
<div>Fancy Button</div>
</button>

Html canvas, pixel manipulation and alpha channel

In html canvas, what I want to achieve is a white noise effect on a picture. So I get the picture, get its ImageData, modify it's alpha and draw it back.
var bat = new Image();
bat.src = "data:image/png;base64,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"
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = 250;
canvas.height = 250;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(bat, 0, 0);
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
if (data[i] != 0 || data[i + 1] != 0 || data[i + 2] != 0) {
data[i + 3] = Math.floor(Math.random() * 255);
}
}
ctx.putImageData(imageData, 0, 0);
requestAnimationFrame(animate);
}
animate();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Bat</title>
<link rel="stylesheet" href="style.css" />
<style>
#main {
display: flex;
flex-direction: row;
}
#canvas {
border: 1px solid black;
width: 150px;
height: 150px;
}
</style>
</head>
<body>
<div id="main">
<canvas id="canvas"></canvas>
<br />
</div>
<script src="script.js"></script>
</body>
</html>
The result is what I need. But the issue is that when you use putImageData, even if the alpha is 0, it won't be transparent.
So I use a temporary canvas, draw the picture on it, modify it and then draw it back on the canvas.
var bat = new Image();
bat.src = "data:image/png;base64,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";
var canvas2 = document.getElementById('canvas2');
var ctx2 = canvas2.getContext('2d');
var tempCanvas = document.createElement('canvas');
var tempContext = tempCanvas.getContext('2d');
canvas2.width = 250;
canvas2.height = 250;
tempCanvas.width = 250;
tempCanvas.height = 250;
var img = new Image();
var alpha = 0;
function animate2() {
alpha += 0.1;
ctx2.clearRect(0, 0, canvas.width, canvas.height);
ctx2.fillStyle = 'blue';
ctx2.fillRect(0, 0, 250, 250);
tempContext.drawImage(bat, 0, 0);
var imageData = tempContext.getImageData(
0,
0,
tempCanvas.width,
tempCanvas.height
);
var data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
if (data[i] != 0 || data[i + 1] != 0 || data[i + 2] != 0) {
//data[i + 3] = Math.floor(Math.random() * 255);
data[i + 3] = 123;
//data[i + 3] = alpha;
}
}
tempContext.putImageData(imageData, 0, 0);
img.src = tempCanvas.toDataURL('image/png');
ctx2.drawImage(img, 0, 0);
requestAnimationFrame(animate2);
}
animate2();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Bat</title>
<link rel="stylesheet" href="style.css" />
<style>
#main {
display: flex;
flex-direction: row;
}
#canvas2 {
border: 1px solid black;
width: 150px;
height: 150px;
}
</style>
</head>
<body>
<div id="main">
<canvas id="canvas"></canvas>
<br />
<canvas id="canvas2"></canvas>
</div>
<script src="script.js"></script>
</body>
</html>
But whenever I want to change the alpha randomly with:
data[i + 3] = Math.floor(Math.random() * 255);
The picture won't display. And if I want to update the alpha other time with:
var alpha = 0;
alpha += 0.1
data[i + 3] = alpha;
The picture flickers...
What is the correct way to get my "white noise" picture that would be transparent so I can see the background through it?
Here is a link of a stackblitz with the demo in it.
First, don't call getImageData every frame. All you need is to know where the black pixels are in the image, these won't change so you can keep the same ImageData object all along, avoid slow read-backs from the GPU.
Then, you can drawImage() a canvas directly. No need to go through a new Image with a toDataURL() which will load your image async and indeed make your animation flicker.
So this would give:
var bat = new Image();
bat.src = "data:image/png;base64,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";
var canvas2 = document.getElementById('canvas2');
var ctx2 = canvas2.getContext('2d');
var tempCanvas = document.createElement('canvas');
var tempContext = tempCanvas.getContext('2d');
canvas2.width = 250;
canvas2.height = 250;
tempCanvas.width = 250;
tempCanvas.height = 250;
// store the ImageData in a way it's accessible at every frame
var imageData;
bat.onload = (evt) => { // always wait for the assets to load
ctx2.drawImage(bat, 0, 0);
imageData = ctx2.getImageData(0, 0, 250, 250);
animate2();
}
var alpha = 0;
function animate2() {
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
ctx2.fillStyle = 'blue';
ctx2.fillRect(0, 0, 250, 250);
var data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
if (data[i] != 0 || data[i + 1] != 0 || data[i + 2] != 0) {
data[i + 3] = Math.floor(Math.random() * 255);
}
}
tempContext.putImageData(imageData, 0, 0);
// drawImage the tempCanvas directly
ctx2.drawImage(tempCanvas, 0, 0);
requestAnimationFrame(animate2);
}
#main {
display: flex;
flex-direction: row;
}
#canvas2 {
border: 1px solid black;
width: 150px;
height: 150px;
}
<div id="main">
<canvas id="canvas2"></canvas>
</div>
But you don't even need a second canvas here, you can draw "behind" the current drawing on a canvas thanks to the "destination-over" compositing mode. You can even use more compositing operations to clip that background so that only the image is "colored":
var bat = new Image();
bat.src = "data:image/png;base64,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";
var canvas2 = document.getElementById('canvas2');
var ctx2 = canvas2.getContext('2d');
canvas2.width = 250;
canvas2.height = 250;
// store the ImageData in a way it's accessible at every frame
var imageData;
bat.onload = (evt) => { // always wait for the assets to load
ctx2.drawImage(bat, 0, 0);
imageData = ctx2.getImageData(0, 0, 250, 250);
animate2();
}
function animate2() {
var data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
if (data[i] != 0 || data[i + 1] != 0 || data[i + 2] != 0) {
data[i + 3] = Math.floor(Math.random() * 255);
}
}
ctx2.putImageData(imageData, 0, 0);
ctx2.globalCompositeOperation = "destination-over"; // draw behind
ctx2.fillStyle = 'blue';
ctx2.fillRect(0, 0, 250, 250);
ctx2.globalCompositeOperation = "destination-in"; // keep only where new pixels are opaque
ctx2.drawImage(bat, 0, 0);
ctx2.globalCompositeOperation = "source-over"; // default
requestAnimationFrame(animate2);
}
#main {
display: flex;
flex-direction: row;
}
#canvas2 {
border: 1px solid black;
width: 150px;
height: 150px;
background: yellow
}
<div id="main">
<canvas id="canvas2"></canvas>
</div>

Creating a Snowflake shape that contains text in shape

I'm trying to create a snowflake on my webpage for the winter season.
The first thing I tried was creating it with SVG:
<h3>Koch Snowflake Frac</h3>
<svg viewBox="-5 -5 110 110" xmlns="http://www.w3.org/2000/svg">
<polyline stroke="cornflowerblue" stroke-width="2" fill="rgba(255,255,255,0.5)" points="55 5,
60 10,
65 10,
65 15,
70 20,
75 20,
80 15,
85 20,
90 20,
85 25,
90 30,
80 30,
75 35,
80 40,
90 40,
85 45,
90 50,
85 50,
80 55,
75 50,
70 50,
65 55,
65 60,
60 60,
55 65,
50 60,
45 60,
45 55,
40 50,
35 50,
30 55,
25 50,
20 50,
25 45,
20 40,
30 40,
35 35,
30 30,
20 30,
25 25,
20 20,
25 20,
30 15,
35 20,
40 20,
45 15,
45 10,
50 10,
55 5" />
<foreignObject x="0" y="0" requiredExtensions="http://www.w3.org/1999/xhtml">
<body xmlns="http://www.w3.org/1999/xhtml">
<p>Here is a paragraph that requires word wrap</p>
</body>
</foreignObject>
</svg>
I could not get the <foreignObject> to work and even if I did it's not supported in IE browsers.
There is no need to support old IE browsers, but I would like support in at least one of them.
Also minor detail at the top, the shape is not closed.
Then I tried creating a snowflake in it with CSS:
.snowflake {
position: absolute;
width: 200px;
display: inline-block;
border-bottom: 10px solid cornflowerblue;
top: 200px;
left: 100px;
background-color: white;
}
.snowflake:before {
position: absolute;
content: "";
display: inline-block;
width: 50px;
border-bottom: 10px solid cornflowerblue;
transform: rotate(45deg);
top: -20px;
}
.snowflake:after {
position: absolute;
content: "";
display: inline-block;
width: 50px;
border-bottom: 10px solid cornflowerblue;
transform: rotate(-45deg);
top: 20px;
}
.smallbranch {
position: absolute;
right: 0px;
display: inline-block;
width: 50px;
border-bottom: 10px solid cornflowerblue;
transform: rotate(45deg);
top: 17px;
box-shadow: -130px -5px 0px 0px cornflowerblue;
}
.smallbranch:before {
position: absolute;
content: "";
display: inline-block;
width: 50px;
border-bottom: 10px solid cornflowerblue;
transform: rotate(90deg);
top: -22px;
left: -22px;
box-shadow: 130px -5px 0px 0px cornflowerblue;
}
.circle {
position: absolute;
left: 50%;
width: 50px;
height: 50px;
border-radius: 50%;
border: 5px solid cornflowerblue;
background-color: white;
transform: translate(-50%, -50%);
}
.circle:before {
position: absolute;
content: "";
display: inline-block;
width: 50px;
border-bottom: 10px solid cornflowerblue;
transform: rotate(90deg);
top: -52px;
left: 20px;
transform: rotate(-45deg);
}
.circle:after {
position: absolute;
content: "";
display: inline-block;
width: 50px;
border-bottom: 10px solid cornflowerblue;
transform: rotate(90deg);
top: 102px;
left: 20px;
transform: rotate(45deg);
}
.branch {
position: absolute;
display: inline-block;
height: 200px;
border-right: 10px solid cornflowerblue;
left: 50%;
top: -100px;
}
<div class="snowflake">
<div class="branch"></div>
<div class="smallbranch"></div>
<div class="circle">Text in here</div>
</div>
This was my best attempt with CSS.
Now here the text is displayed but its not on one line. My idea is to use this in a logo or for a button on the webpage. So I don't think I will need line wrap functionality on the shape, but it would be a plus if it had.
The shape I would like created:
TL;DR
What I would like is a snowflake with text in the middle of the shape.
I'm asking for a solution where the text could be any length and still be inside the shape.
You don't have to create a shape that's exactly the same as what I have tried as long as the shape is a snowflake with text in the center it's ok. I don't know how long the text will be so the shape has to contain the text.
Play with this demo
This is actually a quite interesting question, and coming up with an answer was not easy.
The question asks to make a shape(in this case a snowflake), that would scale to fit the text inside of it. My first advice is to use an image, not try and create the shape with CSS. Images are much easier to make scale, and can have more detail then a CSS shape.
So, lets show how we can accomplish this.
First of all, since you want the element to scale to fit the font, we need to make the element display:inline-block. This will make it only be as wide as it's content, unlike block which would make it as wide as it's parent, and still be able to set the height(which you cannot do with inline).
Next, we need to make the element with a height the same as the width. Luckily, there is a trick in CSS that allows you to do just that. The padding of an element is calculated based on it's width, so if you set the padding-bottom(or padding-top) to 100%, it will have the same width as height.(See this excellent SO answer for further info).
After this, it is just a matter of centering the text inside the snowflake, which may take a little playing with the values to fit your font-family.
If you want the jsfiddle with code:
JSFiddle Demo
Full-Screen JSFiddle Demo
Tested in Chrome, FireFox, IE, and Safari. Minor adjustments may be needed for certain font-family's
.snowflake{
display:inline-block;
background:url("http://i.imgur.com/4M9MH1Q.png") scroll no-repeat center/contain;
}
/*This is for setting the height the same as the width, a 1:1 ratio. more info http://www.mademyday.de/css-height-equals-width-with-pure-css.html#outer_wrap */
.snowflake:after{
content: "";
display: block;
padding-top: 100%;
}
.snowflake span{
display:inline-block;
-webkit-transform: translateY(110%);
-ms-transform: translateY(110%);
transform: translateY(110%);
width:100%;
text-align:center;
padding-top:20%;
}
/*This part is ugly, but it is required to work in chrome or IE, you may have to change the char for different font types*/
.snowflake span:before, .snowflake span:after{
content:"aaa";
visibility:hidden;
opacity:0;
}
Font-size 12pt:
<div class="snowflake" style="font-size:12pt;">
<span>It's Snowing!</span>
</div>
Font-size 24pt:
<div class="snowflake" style="font-size:24pt;">
<span>It's Snowing!</span>
</div>
Font-size 48pt:
<div class="snowflake" style="font-size:48pt;">
<span>It's Snowing!</span>
</div>
EDIT: This solution is prettier, but doesn't work in Chrome or IE
.snowflake{
display:inline-block;
background:url("http://i.imgur.com/4M9MH1Q.png") scroll no-repeat center/contain;
}
/*This is for setting the height the same as the width, a 1:1 ratio. more info http://www.mademyday.de/css-height-equals-width-with-pure-css.html#outer_wrap */
.snowflake:after{
content: "";
display: block;
padding-top: 100%;
}
.snowflake span{
display:inline-block;
transform: translateY(90%);
padding:20%;
}
Font-size 12pt:
<div class="snowflake" style="font-size:12pt;">
<span>It's Snowing!</span>
</div>
Font-size 24pt:
<div class="snowflake" style="font-size:24pt;">
<span>It's Snowing!</span>
</div>
Font-size 48pt:
<div class="snowflake" style="font-size:48pt;">
<span>It's Snowing!</span>
</div>
The main condition for this to work is:
.snowflake must be display:inline-block;
Full-Screen JSFiddle Demo
My solution uses part SVG, part HTML/CSS to create the effect required.
I have used the calc() CSS3 function along with viewport based width/height units which then give it the responsiveness required.
It looks much better when the element is above 200px wide.
calc() Browser Support
Viewport Units Browser Support
The Code
.container {
position: relative;
overflow: auto;
display: block;
width: 50vw;
height: 50vw;
}
.container svg {
width: 100%;
height: 100%;
position: absolute;
}
p {
position: absolute;
z-index: 100;
background: white;
left: 17.5vw;
top: 17.5vw;
margin: 0;
padding: 10px 0;
width: 10vw;
text-align: center;
font-size: 2vw;
border: 20px solid black;
}
#media screen and (min-width: 920px) {
p {
font-size: 3vw;
width: 12.5vw;
}
}
<div class="container">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve" width="50%">
<polygon id="christmas-snowflake-icon" points="441.535,346.644 373.955,307.624 438.697,290.354 431.342,262.782 338.967,287.424
284.535,255.999 339.49,224.271 431.299,249.242 438.787,221.705 374.311,204.168 441.535,165.356 427.266,140.644 359.686,179.66
377.1,114.956 349.545,107.541 324.697,199.861 270.27,231.285 270.27,167.831 337.797,100.809 317.695,80.554 270.27,127.624
270.27,50 241.732,50 241.732,128.036 194.404,80.604 174.203,100.76 241.732,168.438 241.732,231.286 186.779,199.558
162.498,107.565 134.906,114.847 151.957,179.455 84.732,140.644 70.465,165.356 138.045,204.373 73.303,221.645 80.66,249.218
173.035,224.574 227.465,255.999 172.51,287.727 80.701,262.758 73.211,290.293 137.688,307.832 70.465,346.644 84.732,371.356
152.312,332.337 134.898,397.042 162.457,404.459 187.303,312.137 241.732,280.711 241.732,344.169 174.203,411.191
194.307,431.446 241.732,384.376 241.732,462 270.27,462 270.27,383.964 317.598,431.396 337.797,411.24 270.27,343.562
270.27,280.712 325.223,312.439 349.502,404.435 377.094,397.15 360.043,332.545 427.268,371.356 "></polygon>
</svg>
<p>This is some text Now</p>
</div>
CodePen
Using svg i have managed to make an almost responsive solution
.box{
display:inline-block;
position:relative;
width:300px;
height:300px;
}
.box:after{
position:absolute;
content:"Some text";
width:20%;
height:20%;
padding:5%;
font-size:100%;
left:calc(50% - 15%);
top:calc(50% - 19%);
}
<div class="box">
<svg viewBox="0 0 99.999997 100" height="100%" width="100%">
<g transform="translate(0,-952.36216)" id="layer1">
<path id="path4701" d="m 23,959 5,-3 6,11 6,-11 6,0 -9,17 4,7 8,-14 7,13 4,-7 -7,-13 3,-5 7,13 6,-11 4,2 -6,11 12,0 3,5 -18,0 -4,8 16,0 -7,13 8,0.12 7,-13 6,0 -7,13 12,0 -0.12,6 -12,-0 5,11 -3,5 -9,-17 -8,0.12 8,14 -16,0 4,8 18,0 -3,5 -12,-0.06 6,11 -4,3 -6,-11 -7,13 -3,-5 7,-13 -4,-7 -7,14 -8,-14 -4,7 9,17 -6,0.12 -6,-11 -6,11 -4,-3 6,-11 -14,-0.12 3,-6 15,0.12 4,-8 -15,-0.063 7,-14 -8,0 -9,17 -3,-5 6,-11 -12,0 0,-6 12,-0.06 -7,-13 6,-0.12 7,13 8,0.06 -7,-13 15,0.06 -4,-8 -15,-0.06 -3,-5 14,-0.06 z" style="fill:#2ad4ff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
</g>
</svg>
</div>
Try re sizing in the following snippet,it stays almost responsive if width and height are increased equally
.box{
display:inline-block;
position:relative;
width:300px;
height:300px;
resize:both;
border:2px solid;
overflow:auto;
}
.box:after{
position:absolute;
content:"Some text";
width:20%;
height:20%;
padding:5%;
font-size:100%;
left:calc(50% - 15%);
top:calc(50% - 19%);
}
<div class="box">
<svg viewBox="0 0 99.999997 100" height="100%" width="100%">
<g transform="translate(0,-952.36216)" id="layer1">
<path id="path4701" d="m 23,959 5,-3 6,11 6,-11 6,0 -9,17 4,7 8,-14 7,13 4,-7 -7,-13 3,-5 7,13 6,-11 4,2 -6,11 12,0 3,5 -18,0 -4,8 16,0 -7,13 8,0.12 7,-13 6,0 -7,13 12,0 -0.12,6 -12,-0 5,11 -3,5 -9,-17 -8,0.12 8,14 -16,0 4,8 18,0 -3,5 -12,-0.06 6,11 -4,3 -6,-11 -7,13 -3,-5 7,-13 -4,-7 -7,14 -8,-14 -4,7 9,17 -6,0.12 -6,-11 -6,11 -4,-3 6,-11 -14,-0.12 3,-6 15,0.12 4,-8 -15,-0.063 7,-14 -8,0 -9,17 -3,-5 6,-11 -12,0 0,-6 12,-0.06 -7,-13 6,-0.12 7,13 8,0.06 -7,-13 15,0.06 -4,-8 -15,-0.06 -3,-5 14,-0.06 z" style="fill:#2ad4ff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
</g>
</svg>
</div>
Using Canvas:
The snowflake can also be created programmatically using HTML5 Canvas. Doing it programmatically allows for better control over the text and keeps it within the container at all times. I am certain that this method can be converted into its equivalent SVG version but am more comfortable with Canvas.
One disadvantage of using Canvas is that the output is not responsive. It becomes blurred (pixelated) when scaled. The only way to avoid it is to redraw the shape once again whenever there is a change to the text (or) dimensions etc.
Construction
The shape is actually comprised of three parts and they are as follows:
Inner star with 6 spikes (the green colored star)
The lines (red colored)
Outer star with 6 spikes (the blue colored star)
The stars are drawn using the same approach as described in my answer here. Basically we assign an inner and an outer radius to each of them, find points on the inner and outer circle and then connect them alternately to produce the star.
The lines are also drawn using a similar approach except that it has only one radius and the lines are drawn from the points on the (imaginary) inner circle of the green star to specified points on the circle.
Calculation of dimensions: Since the text has to be fit within the shape and the shape must expand to fit the text, the first step that needs to be done is to calculate the width that the text requires. This is done using measureText().width. The value that is obtained is set as the radius of the green star's inner circle (because the text has to remain within it).
Finally, since the outer blue star should look as though it is kind of clipped (not appear in full), height and width lesser than that of the blue star's outer radius is set and a border-radius is assigned to the canvas element.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d"),
spikes = 6,
step = Math.PI / spikes,
rot; /* no. of spikes for the stars */
function drawSnowFlake(content, font) {
ctx.font = font; /* font of the text */
/* get width required to fit text and set radius of each star */
var text = ctx.measureText(content);
innerRadius = (text.width / 2) * 1.15; /* extra factor is to leave gap between text and shape */
outerRadius = text.width;
/* set center point for the individual parts of the shape */
x = leftOffset = outerRadius * 1.5;
y = topOffset = outerRadius * 1.5;
/* canvas height and width should be set same as the largest star for clip */
canvas.height = outerRadius * 3;
canvas.width = outerRadius * 3;
/* default settings */
rot = Math.PI / 2 * 3;
ctx.beginPath();
ctx.lineWidth = 15; /* thickness of the lines */
ctx.strokeStyle = 'blue'; /* color of the lines */
ctx.font = font; /* font of the text */
/* create the inner star */
ctx.moveTo(leftOffset, topOffset - outerRadius)
for (i = 0; i < spikes; i++) {
x = leftOffset + Math.cos(rot) * outerRadius;
y = topOffset + Math.sin(rot) * outerRadius;
ctx.lineTo(x, y);
rot += step;
x = leftOffset + Math.cos(rot) * innerRadius;
y = topOffset + Math.sin(rot) * innerRadius;
ctx.lineTo(x, y);
rot += step;
}
ctx.lineTo(leftOffset, topOffset - outerRadius);
ctx.closePath();
ctx.stroke();
ctx.restore();
/* draws the outer star */
ctx.beginPath();
ctx.moveTo(leftOffset, topOffset - (outerRadius * 1.725));
for (i = 0; i < spikes; i++) {
x = leftOffset + Math.cos(rot) * (outerRadius * 1.725);
y = topOffset + Math.sin(rot) * (outerRadius * 1.725);
ctx.lineTo(x, y)
rot += step
x = leftOffset + Math.cos(rot) * (outerRadius * 1.15);
y = topOffset + Math.sin(rot) * (outerRadius * 1.15);
ctx.lineTo(x, y);
rot += step;
}
ctx.lineTo(leftOffset, topOffset - (outerRadius * 1.725));
ctx.closePath();
ctx.stroke();
ctx.restore();
/* draws the lines from the stars */
rot = Math.PI / 3;
ctx.beginPath();
for (i = 0; i < spikes; i++) {
x = leftOffset + Math.cos(rot) * innerRadius;
y = topOffset + Math.sin(rot) * innerRadius;
x2 = leftOffset + Math.cos(rot) * (outerRadius * 1.5);
y2 = topOffset + Math.sin(rot) * (outerRadius * 1.5);
ctx.moveTo(x, y);
ctx.lineTo(x2, y2);
rot += 2 * Math.PI / spikes;
}
ctx.closePath();
ctx.stroke();
/* add text and position it */
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.fillText(content, leftOffset, topOffset);
}
document.getElementById('draw').addEventListener('click', function() {
var input = document.getElementById('content').value;
var fontsize = document.getElementById('fontsize').value;
var fontname = document.getElementById('fontname').value;
drawSnowFlake(input, fontsize + "px " + fontname);
});
drawSnowFlake("TEXT HERE", "16px Arial");
div {
margin-bottom: 10px;
}
canvas {
border-radius: 50%;
}
<div class='controls'>
<input id='content' type='textbox' value='TEXT HERE' />
<select id='fontsize'>
<option value='10'>10px</option>
<option value='12'>12px</option>
<option value='14'>14px</option>
<option value='16' selected>16px</option>
</select>
<select id='fontname'>
<option value='Arial' selected>Arial</option>
<option value='Verdana'>Verdana</option>
<option value='Courier'>Courier</option>
</select>
<button id='draw'>Draw</button>
</div>
<canvas id='canvas'></canvas>
With Text Wrap and Bevelled Edges:
Here is a more complex demo which also supports wrapping of the text into multiple lines if content exceeds a certain width. The below is what this snippet will do:
If the size required for the text is less than max-width, shrink the shape
If the size required for the text (height or width) is more than max-width, split the text into multiple lines, expand the shape to fit the text in center
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d"),
spikes = 6,
/* no. of spikes for the stars */
step = Math.PI / spikes,
rot, maxWidth = 100,
lineHeight = 20;
function drawSnowFlake(content, font) {
ctx.font = font; /* font of the text */
/* get width & height required to fit text and set radius of each star */
var text = ctx.measureText(content);
var width = text.width;
var height = splitText(ctx, content, maxWidth, lineHeight);
/* decide which among height & width should be used for radius */
if (width < maxWidth && height < maxWidth) {
innerRadius = (width / 2) * 1.15; /* extra factor is to leave gap between text and shape */
outerRadius = width;
} else if (width > maxWidth && height < maxWidth) {
innerRadius = (maxWidth / 2) * 1.15; /* extra factor is to leave gap between text and shape */
outerRadius = maxWidth;
} else {
innerRadius = (height / 2) * 1.15; /* extra factor is to leave gap between text and shape */
outerRadius = height;
}
/* set center point for the individual parts of the shape */
x = leftOffset = outerRadius * 1.5;
y = topOffset = outerRadius * 1.5;
/* canvas height and width should be set same as the largest star for clip */
canvas.height = outerRadius * 3;
canvas.width = outerRadius * 3;
/* default settings */
rot = Math.PI / 2 * 3;
ctx.beginPath();
ctx.lineWidth = 15; /* thickness of the lines */
ctx.lineJoin = 'bevel';
ctx.strokeStyle = 'blue'; /* color of the lines */
ctx.font = font; /* font of the text */
/* create the inner star */
ctx.moveTo(leftOffset, topOffset - outerRadius)
for (i = 0; i < spikes; i++) {
x = leftOffset + Math.cos(rot) * outerRadius;
y = topOffset + Math.sin(rot) * outerRadius;
ctx.lineTo(x, y);
rot += step;
x = leftOffset + Math.cos(rot) * innerRadius;
y = topOffset + Math.sin(rot) * innerRadius;
ctx.lineTo(x, y);
rot += step;
}
ctx.lineTo(leftOffset, topOffset - outerRadius);
ctx.closePath();
ctx.stroke();
ctx.restore();
/* draws the outer star */
ctx.beginPath();
ctx.moveTo(leftOffset, topOffset - (outerRadius * 1.725));
for (i = 0; i < spikes; i++) {
x = leftOffset + Math.cos(rot) * (outerRadius * 1.725);
y = topOffset + Math.sin(rot) * (outerRadius * 1.725);
ctx.lineTo(x, y)
rot += step
x = leftOffset + Math.cos(rot) * (outerRadius * 1.15);
y = topOffset + Math.sin(rot) * (outerRadius * 1.15);
ctx.lineTo(x, y);
rot += step;
}
ctx.lineTo(leftOffset, topOffset - (outerRadius * 1.725));
ctx.closePath();
ctx.stroke();
ctx.restore();
/* draws the lines from the stars */
rot = Math.PI / 3;
ctx.beginPath();
for (i = 0; i < spikes; i++) {
x = leftOffset + Math.cos(rot) * innerRadius;
y = topOffset + Math.sin(rot) * innerRadius;
x2 = leftOffset + Math.cos(rot) * (outerRadius * 1.5);
y2 = topOffset + Math.sin(rot) * (outerRadius * 1.5);
ctx.moveTo(x, y);
ctx.lineTo(x2, y2);
rot += 2 * Math.PI / spikes;
}
ctx.closePath();
ctx.stroke();
/* add text and position it */
wrapText(ctx, content, leftOffset, (topOffset - ((height - lineHeight) / 2)), maxWidth, lineHeight);
}
document.getElementById('draw').addEventListener('click', function() {
var input = document.getElementById('content').value;
var fontsize = document.getElementById('fontsize').value;
var fontname = document.getElementById('fontname').value;
drawSnowFlake(input, fontsize + "px " + fontname);
});
/* split text into lines based on width and calculate required height */
function splitText(context, text, maxWidth, lineHeight) {
var words = text.split(' ');
var line = '',
height = lineHeight;
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
line = words[n] + ' ';
height += lineHeight;
} else {
line = testLine;
}
}
return height;
}
/* source from http://www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial/ */
function wrapText(context, text, x, y, maxWidth, lineHeight) {
var words = text.split(' ');
var line = '';
context.textBaseline = "middle";
context.textAlign = "center";
var topOffset = x;
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
context.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
} else {
line = testLine;
}
}
context.fillText(line, x, y);
}
drawSnowFlake('CSS SHAPES, SVG, CANVAS DESIGNS ROCK', "16px Arial");
div {
margin-bottom: 10px;
}
canvas {
border-radius: 50%;
}
<div class='controls'>
<input id='content' type='textbox' value='CSS SHAPES, SVG, CANVAS DESIGNS ROCK' />
<select id='fontsize'>
<option value='10'>10px</option>
<option value='12'>12px</option>
<option value='14'>14px</option>
<option value='16' selected>16px</option>
</select>
<select id='fontname'>
<option value='Arial' selected>Arial</option>
<option value='Verdana'>Verdana</option>
<option value='Courier'>Courier</option>
</select>
<button id='draw'>Draw</button>
</div>
<canvas id='canvas'></canvas>
The OP wanted the snowflake to scale to fit the size of the text. Most of the other answers are doing it the other way around.
Here's the simplest solution I could come up width. It is mostly just HTML and SVG with a tiny snippet of JS. This is required because I don't believe it is possible to have an SVG scale to fit a parent that doesn't have an explicit size.
Change the text content or the CSS style of the inner <div> to your heart's content and the SVG snowflake will scale to match.
You could almost certainly do away with the JS if you were happy to use a bitmap background image instead of an SVG.
$().ready(function() {
divWidth = $(".snowflake div").outerWidth();
$(".snowflake svg").css("width", divWidth + "px");
});
.snowflake
{
display: inline-block;
position: relative;
}
.snowflake svg
{
position: absolute;
fill: #eef;
}
.snowflake DIV
{
position: absolute;
padding: 100px;
font: 30pt sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="snowflake">
<svg viewBox="2 0 32 36">
<path d="M33.212,26.16l-3.054-1.764l1.84-1.062c0.238-0.139,0.32-0.441,0.184-0.684c-0.14-0.238-0.445-0.322-0.684-0.183 L29.16,23.82l-2.32-1.34l4.729-2.73c0.239-0.139,0.321-0.441,0.184-0.684c-0.139-0.238-0.445-0.322-0.684-0.183l-5.23,3.019 l-3.619-2.09l4.352-1.918l-4.354-1.919l3.619-2.091l5.231,3.021c0.079,0.047,0.165,0.067,0.25,0.067 c0.174,0,0.342-0.091,0.435-0.25c0.139-0.239,0.057-0.546-0.184-0.683l-4.731-2.732l2.32-1.34L31.5,13.32 c0.079,0.046,0.165,0.066,0.25,0.066c0.173,0,0.341-0.09,0.435-0.25c0.138-0.238,0.056-0.545-0.184-0.682L30.16,11.39l3.052-1.762 c0.239-0.139,0.32-0.443,0.184-0.684c-0.14-0.238-0.446-0.322-0.684-0.184l-3.051,1.763L29.66,8.401c0-0.275-0.225-0.5-0.5-0.5 c-0.276,0-0.5,0.225-0.5,0.5l0.001,2.699l-2.32,1.34l0.001-5.46c0-0.276-0.224-0.5-0.5-0.5c-0.275,0-0.5,0.224-0.5,0.5 l-0.001,6.037l-3.619,2.09l0.515-4.728l-3.838,2.81V9.008l5.229-3.021c0.238-0.138,0.32-0.443,0.184-0.684 c-0.14-0.238-0.445-0.321-0.684-0.182l-4.729,2.73V5.173l2.339-1.352c0.239-0.138,0.321-0.443,0.184-0.684 c-0.14-0.238-0.445-0.322-0.684-0.182L18.399,4.02V0.5c0-0.276-0.224-0.5-0.5-0.5s-0.5,0.224-0.5,0.5v3.523L15.56,2.961 c-0.24-0.141-0.545-0.057-0.683,0.184c-0.138,0.239-0.056,0.545,0.183,0.684l2.339,1.352v2.678l-4.729-2.73 c-0.24-0.14-0.545-0.057-0.683,0.184c-0.138,0.239-0.056,0.545,0.183,0.684l5.229,3.02v4.184l-3.837-2.811l0.514,4.729 l-3.621-2.092V6.989c0-0.276-0.224-0.5-0.5-0.5c-0.276,0-0.5,0.224-0.5,0.5v5.462l-2.318-1.34L7.136,8.41 c0-0.277-0.224-0.5-0.5-0.5c-0.276,0-0.5,0.223-0.5,0.5l0.001,2.125L3.084,8.771C2.845,8.63,2.539,8.714,2.401,8.955 C2.263,9.194,2.345,9.5,2.584,9.638L5.636,11.4l-1.839,1.062c-0.239,0.139-0.321,0.443-0.183,0.684 c0.093,0.16,0.261,0.25,0.434,0.25c0.085,0,0.171-0.021,0.25-0.066l2.339-1.351l2.319,1.339l-4.729,2.73 c-0.239,0.139-0.321,0.443-0.183,0.684c0.093,0.16,0.261,0.25,0.434,0.25c0.085,0,0.171-0.021,0.25-0.066l5.23-3.021l3.622,2.091 l-4.352,1.919l4.351,1.919l-3.621,2.09l-5.231-3.018c-0.241-0.138-0.545-0.058-0.683,0.184c-0.138,0.24-0.056,0.545,0.183,0.686 l4.731,2.729l-2.321,1.34l-2.338-1.352c-0.239-0.142-0.545-0.058-0.683,0.184c-0.138,0.238-0.056,0.545,0.183,0.684l1.838,1.062 l-3.05,1.76c-0.239,0.139-0.321,0.443-0.183,0.684c0.093,0.16,0.261,0.25,0.434,0.25c0.085,0,0.171-0.021,0.25-0.065l3.051-1.763 L6.14,27.4c0,0.276,0.224,0.5,0.5,0.5l0,0c0.276,0,0.5-0.225,0.5-0.5l-0.001-2.701l2.322-1.34l-0.002,5.463 c0,0.277,0.224,0.5,0.5,0.5s0.5-0.223,0.5-0.5l0.002-6.041l3.619-2.09l-0.514,4.729l3.837-2.81v4.183l-5.228,3.021 c-0.239,0.139-0.321,0.442-0.183,0.684c0.138,0.236,0.444,0.318,0.683,0.184l4.728-2.73v2.679l-2.339,1.353 c-0.239,0.139-0.321,0.442-0.183,0.684c0.138,0.236,0.444,0.32,0.683,0.184l1.839-1.062V35.3c0,0.274,0.224,0.5,0.5,0.5 s0.5-0.226,0.5-0.5v-3.524l1.841,1.062c0.079,0.046,0.165,0.066,0.25,0.066c0.174,0,0.342-0.09,0.435-0.25 c0.139-0.239,0.057-0.545-0.184-0.684l-2.341-1.354v-2.678l4.729,2.73c0.079,0.046,0.165,0.066,0.25,0.066 c0.174,0,0.342-0.09,0.435-0.25c0.139-0.239,0.057-0.545-0.184-0.684l-5.229-3.021V22.6l3.838,2.811l-0.514-4.729l3.62,2.09v6.039 c0,0.276,0.224,0.5,0.5,0.5c0.275,0,0.5-0.224,0.5-0.5V23.35l2.318,1.34l0.001,2.699c0,0.275,0.225,0.5,0.5,0.5s0.5-0.225,0.5-0.5 l-0.001-2.123l3.053,1.764c0.079,0.045,0.165,0.066,0.25,0.066c0.174,0,0.342-0.09,0.435-0.25 C33.536,26.604,33.454,26.296,33.212,26.16z M20.997,23.259l-2.6-1.901l-0.499-0.363l-0.501,0.365l-2.598,1.9l0.348-3.201 l0.067-0.615l-0.567-0.25l-2.945-1.299l2.946-1.299l0.566-0.25l-0.067-0.616l-0.348-3.2l2.598,1.901l0.5,0.364l0.5-0.365l2.6-1.901 l-0.349,3.201l-0.066,0.616l0.564,0.249l2.946,1.3l-2.944,1.299l-0.566,0.25l0.066,0.615L20.997,23.259z"/>
</svg>
<div>Here is some text. It's even wrapped.</div>
</div>

Inverse Canvas Colors

This code produces a mathematical object: a white geometric shape that builds upon a white background. I can change the background color in the canvas tag, and the color of the lines that build the shape. The problem is a black square remains even when I change the canvas color. My goal is just to simply invert the colors, from a black background with a white shape to a black shape with a white background.
var canvas;
var ctx;
var canvasWidth = 600;
var canvasHeight = 600;
var circleR = 300;
var timeout = 0;
var often = 15;
function init() {
if (location.hash)
often = 5;
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
drawLines();
}
function drawLines() {
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
ctx.translate(canvasWidth / 2, canvasHeight / 2);
for (var i = 0; i < 25; i++) {
for (var a = -45; a <= 45; a += often) {
setTimeout("drawTimeout(" + a + ");", 100 * timeout);
timeout++;
}
}
}
function drawTimeout(a) {
ctx.beginPath();
ctx.moveTo(0, circleR);
var radians = Math.PI / 180 * a;
var x = (circleR * Math.sin(radians)) / Math.sin(Math.PI / 2 - radians);
ctx.lineTo(x, 0);
if (Math.abs(a) == 45) {
ctx.strokeStyle = "rgb(255,255,255)";
ctx.lineWidth = 1;
} else if (a == 0) {
ctx.strokeStyle = "rgb(200,200,200)";
ctx.lineWidth = 0.5;
} else {
ctx.strokeStyle = "rgb(110,110,110)";
ctx.lineWidth = 0.2;
}
ctx.stroke();
ctx.rotate((Math.PI / 180) * 15);
}
function redirect() {
if (window.location.hash) window.location.href = '';
else window.location.href = '#more';
window.location.reload(true);
}
init();
body {
margin: 0;
background-color: black;
}
canvas {
display: block;
margin: 10px auto;
background-color: black;
}
<canvas id="canvas" width="600" height="600"></canvas>
Here is a white on black version of your animation, didn't made so much changes, just the stroke colors and css.
var canvas;
var ctx;
var canvasWidth = 600;
var canvasHeight = 600;
var circleR = 300;
var timeout = 0;
var often = 15;
function init() {
if (location.hash)
often = 5;
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.fillStyle = "#FFF";
drawLines();
}
function drawLines() {
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
ctx.translate(canvasWidth / 2, canvasHeight / 2);
for (var i = 0; i < 25; i++) {
for (var a = -45; a <= 45; a += often) {
setTimeout("drawTimeout(" + a + ");", 100 * timeout);
timeout++;
}
}
}
function drawTimeout(a) {
ctx.beginPath();
ctx.moveTo(0, circleR);
var radians = Math.PI / 180 * a;
var x = (circleR * Math.sin(radians)) / Math.sin(Math.PI / 2 - radians);
ctx.lineTo(x, 0);
// store a variable for our color, since you only use shades of grey;
var c;
if (Math.abs(a) == 45) {
c = 0; // 255-255
ctx.strokeStyle = "rgb("+c+","+c+","+c+")";
ctx.lineWidth = 1;
} else if (a == 0) {
c = 55; // 255-200
ctx.strokeStyle = "rgb("+c+","+c+","+c+")";
ctx.lineWidth = 0.5;
} else {
c = 145; // 255-110
ctx.strokeStyle = "rgb("+c+","+c+","+c+")";
ctx.lineWidth = 0.2;
}
ctx.stroke();
ctx.rotate((Math.PI / 180) * 15);
}
function redirect() {
if (window.location.hash) window.location.href = '';
else window.location.href = '#more';
window.location.reload(true);
}
init();
body {
margin: 0;
background-color: black;
}
canvas {
display: block;
margin: 10px auto;
background-color: white;
}
<canvas id="canvas" width="600" height="600"></canvas>

CSS - how to create circle pie canvas like this?

I really like this element,
but how to create it? I am not sure what's the correct designation of the element...
Thank you very much.
This effect can be achieved by layering a couple arc()s:
// bright blue full circle
d.beginPath();
d.arc(50, 50, 50, 0, 2 * Math.PI, false);
d.fillStyle = "#aaeeff";
d.fill();
// dark blue percentage circle
d.beginPath();
d.moveTo(50, 50);
d.arc(50, 50, 50, -0.5 * Math.PI, 0.78 * 2 * Math.PI - 0.5 * Math.PI, false);
d.fillStyle = "#00aaff";
d.fill();
// white inner filler
d.beginPath();
d.moveTo(50, 50);
d.arc(50, 50, 25, 0, 2 * Math.PI, false);
d.fillStyle = "#ffffff";
d.fill();
and finally rendering the text:
d.moveTo(50, 50);
d.fillStyle = "#606060";
d.font = "12pt sans-serif";
d.fillText("78%", 36, 56);
Fiddle: http://jsfiddle.net/j6NVg/
Instead of using the <canvas> element, I have chosen to construct the pie chart relying on CSS and JS entirely. The HTML markup is as follow:
<div class="pie" data-percent="78">
<div class="left">
<span></span>
</div>
<div class="right">
<span></span>
</div>
</div>
The CSS is as follow. The trick is to split the circle into two halves (the nested .left and .right elements). The halves will have their overflowing content hidden, and contain nested <span> that we will manipulate with JS for rotation later. Add vendor prefixes when appropriate :)
.pie {
background-color: #eee;
border-radius: 50%;
width: 200px;
height: 200px;
overflow: hidden;
position: relative;
}
.pie > div {
float: left;
width: 50%;
height: 100%;
position: relative;
overflow: hidden;
}
.pie span {
background-color: #4a7298;
display: block;
width: 100%;
height: 100%;
}
.pie .left span {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
-webkit-transform-origin: 100% 50%;
transform-origin: 100% 50%;
}
.pie .right span {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
-webkit-transform-origin: 0% 50%;
transform-origin: 0% 50%;
}
.pie:before,
.pie:after {
border-radius: 50%;
display: block;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
}
.pie:before {
background-color: #fff;
content: "";
width: 75%;
height: 75%;
z-index: 100;
}
.pie:after {
content: attr(data-percent) "%";
z-index: 200;
text-align: center;
}
I have used the following with jQuery:
$(function() {
$(".pie").each(function() {
var percent = $(this).data("percent").slice(0,-1), // Removes '%'
$left = $(this).find(".left span"),
$right = $(this).find(".right span"),
deg;
if(percent<=50) {
// Hide left
$left.hide();
// Adjust right
deg = 180 - (percent/100*360)
$right.css({
"transform": "rotateZ(-"+deg+"deg)"
});
} else {
// Adjust left
deg = 180 - ((percent-50)/100*360)
$left.css({
"transform": "rotateZ(-"+deg+"deg)"
});
}
});
});
Here is the fiddle: http://jsfiddle.net/Aw5Rf/7/
Check the below links for more info (not an exact one.But you can get some idea).
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Canvas Test</title>
</head>
<body>
<section>
<div>
<canvas id="canvas" width="400" height="300">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
</div>
<script type="text/javascript">
var myColor = ["#ECD078","#D95B43","#C02942","#542437","#53777A"];
var myData = [10,30,20,60,40];
function getTotal(){
var myTotal = 0;
for (var j = 0; j < myData.length; j++) {
myTotal += (typeof myData[j] == 'number') ? myData[j] : 0;
}
return myTotal;
}
function plotData() {
var canvas;
var ctx;
var lastend = 0;
var myTotal = getTotal();
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < myData.length; i++) {
ctx.fillStyle = myColor[i];
ctx.beginPath();
ctx.moveTo(200,150);
ctx.arc(200,150,150,lastend,lastend+
(Math.PI*2*(myData[i]/myTotal)),false);
ctx.lineTo(200,150);
ctx.fill();
lastend += Math.PI*2*(myData[i]/myTotal);
}
}
plotData();
</script>
</section>
</body>
</html>
For more info :Graphing Data in the HTML5 Canvas Element Simple Pie Charts
Another Link : Pure CSS3 Pie Charts effect
This is an online demo: http://jsbin.com/uFaSOwO/1/
First of all what you need can be done exactly using jQuery knob plugin. Still interested in a CSS Solution, than here's what I have done
<div class="load_me"></div>
.load_me {
margin: 100px;
height: 50px;
width: 50px;
border: 5px solid #f00;
border-radius: 50%;
border-top-color: transparent;
}
Demo
Animating the Knob Credits
If you want to prevent the mouse alteration, you can simply add readOnly
$this.knob({
readOnly: true
});
Demo
FIDDLE with ANIMATION
Here's my approach:
var ctx = canvas.getContext('2d');
/*
* in canvas, 0 degrees angle is on the right edge of a circle,
* while we want to start at the top edge of the circle.
* We'll use this variable to compensate the difference.
*/
var relativeAngle = 270;
function drawCanvas() {
ctx.clearRect(0, 0, 90, 90);
//light blue circle
ctx.lineWidth = 20;
ctx.strokeStyle = '#D8E8F7';
ctx.beginPath();
ctx.arc(45, 45, 35, 0, 2*Math.PI);
ctx.stroke();
//dark blue circle
ctx.strokeStyle = '#66ADF4';
ctx.beginPath();
//notice the angle conversion from degrees to radians in the 5th argument
ctx.arc(45, 45, 35, 1.5*Math.PI, ((angle + relativeAngle) / 180) * Math.PI);
ctx.stroke();
//text
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.fillStyle = '#666';
ctx.font = 'bold 14px serif';
// angle conversion to percentage value
ctx.fillText(parseInt(100 * angle / 360).toString() + '%', 45, 45);
}
var angle;
function timeout() {
angle = parseInt(360 * percent / 100);
drawCanvas();
if (angle > 360) {
document.getElementById('run').disabled = false;
percent = 0;
return;
}
percent++;
setTimeout(timeout, 10);
};
var percent = 0;
/* START the ANIMATION */
timeout();
At the bottom of the code you'll find a self evaluating function timeout which calls the drawCanvas function every 10 miliseconds and increments the blue circle angle. I hope everything is clear here. If not, feel free to ask!
Enjoy it!