Related
I wanted to make a rectangle move in 4 directions with a click of a button on JavaScript. Only the Right and Down works and the other two does not work. I tried finding it on internet and so far had not have any luck.
var currentXpos = 0;
function moveRectRight() {
var rect = document.getElementById('rectangle');
currentXpos += 100; // move by 100 px to the right
rect.style.marginLeft = currentXpos + 'px'; // re-draw rectangle
}
function moveRectLeft() {
var rect = document.getElementById('rectangle');
currentXpos += 100; // move by 100 px to the right
rect.style.marginRight = currentXpos + 'px'; // re-draw rectangle
}
function moveRectUp() {
var rect = document.getElementById('rectangle');
currentXpos += 100; // move by 100 px to the right
rect.style.marginBottom = currentXpos + 'px'; // re-draw rectangle
}
function moveRectDown() {
var rect = document.getElementById('rectangle');
currentXpos += 100; // move by 100 px to the right
rect.style.marginTop = currentXpos + 'px'; // re-draw rectangle
}
#rectangle {
background-color: red;
width: 200px;
height: 100px;
margin-left: 0px;
}
<div id='rectangle'></div>
<input type="button" value="Right" onclick="moveRectRight()" />
<input type="button" value="Left" onclick="moveRectLeft()" />
<input type="button" value="Up" onclick="moveRectUp()" />
<input type="button" value="Down" onclick="moveRectDown()" />
Your problem lies on this code
function moveRectLeft() {
var rect = document.getElementById('rectangle');
currentXpos += 100; // move by 100 px to the right
rect.style.marginRight = currentXpos + 'px'; // re-draw rectangle
}
function moveRectUp() {
var rect = document.getElementById('rectangle');
currentXpos += 100; // move by 100 px to the right
rect.style.marginBottom = currentXpos + 'px'; // re-draw rectangle
}
when you move left you tried to add the margin right and when you move up you add margin bottom. This is a wrong concept, you shouldn't imagine it like the box is being pushed from 4 side like this image
When you code in HTML & CSS, try to imagine that in coordinate, the 0,0 (x and y) is on your upper left corner of browser, and to move them you can only move them away or closer to the 0,0, like below
I suggest you to learn/debug using the developer tools you can see where it goes wrong,
So the answer is just changing the code to marginLeft and marginTop
That aside, I made my own version maybe you want to check it out
<html>
<head>
<style>
#rectangle {
background-color: red;
width: 200px;
height: 100px;
position: fixed;
}
</style>
</head>
<body>
<div id='rectangle' style="top:100px;left:100px;"></div>
<input type="button" value="Right" onclick="moveRect(this)" />
<input type="button" value="Left" onclick="moveRect(this)" />
<input type="button" value="Up" onclick="moveRect(this)" />
<input type="button" value="Down" onclick="moveRect(this)" />
<script>
const distance = 10;
const directionMap = {
'Up': {
'prop': 'top',
'value': -1
},
'Down': {
'prop': 'top',
'value': 1
},
'Left': {
'prop': 'left',
'value': -1
},
'Right': {
'prop': 'left',
'value': 1
},
}
const parsePosition = (prop) => parseFloat(rectangle.style[prop]) || 0;
const moveRect = (element) => {
let {
prop,
value
} = directionMap[element.value];
rectangle.style[prop] = (parsePosition(prop) + (value * distance)) + "px";
}
</script>
</body>
</html>
Because margins in the HTML, depend on having a neightbor. So, you'll not see margin-right and margin-bottom working, hence you'll not see the box going up or left.
Instead, what you can do, is affect the same property with addition and substraction. For Y affect only margin-top and for X affect only margin-left
CSS Documentation
<html>
<head>
<style>
#rectangle {
background-color: red;
width: 200px;
height: 100px;
margin-left: 0px;
}
</style>
</head>
<body>
<div id='rectangle'>
</div>
<input type="button" value="Right" onclick="moveRectRight()" />
<input type="button" value="Left" onclick="moveRectLeft()" />
<input type="button" value="Up" onclick="moveRectUp()" />
<input type="button" value="Down" onclick="moveRectDown()" />
<script>
var currentXpos = 0;
function moveRectRight() {
var rect = document.getElementById('rectangle');
console.log(rect)
currentXpos += 100; // move by 100 px to the right
rect.style.marginLeft = currentXpos + 'px'; // re-draw rectangle
}
function moveRectLeft() {
var rect = document.getElementById('rectangle');
currentXpos -= 100; // move by 100 px to the right
rect.style.marginLeft = currentXpos + 'px'; // re-draw rectangle
}
function moveRectUp() {
var rect = document.getElementById('rectangle');
currentXpos -= 100; // move by 100 px to the right
rect.style.marginTop = currentXpos + 'px'; // re-draw rectangle
}
function moveRectDown() {
var rect = document.getElementById('rectangle');
currentXpos += 100; // move by 100 px to the right
rect.style.marginTop = currentXpos + 'px'; // re-draw rectangle
}
</script>
</body>
</html>
Thremulant gave a very good solution but there was something missed something the "current position" variable should be different for X and Y axis. This way it will not show abnormal behaviour.
<html>
<head>
<style>
#rectangle {
background-color: red;
width: 200px;
height: 100px;
margin-left: 0px;
}
</style>
<script>
var currentXpos = 0;
var currentYpos = 0;
function moveRectRight() {
var rect = document.getElementById('rectangle');
currentXpos += 100; // move by 100 px to the right
rect.style.marginLeft = currentXpos + 'px'; // re-draw rectangle
}
function moveRectLeft() {
var rect = document.getElementById('rectangle');
currentXpos -= 100; // move by 100 px to the right
rect.style.marginLeft = currentXpos + 'px'; // re-draw rectangle
}
function moveRectUp() {
var rect = document.getElementById('rectangle');
currentYpos -= 100; // move by 100 px to the right
rect.style.marginTop = currentYpos + 'px'; // re-draw rectangle
}
function moveRectDown() {
var rect = document.getElementById('rectangle');
currentYpos += 100; // move by 100 px to the right
rect.style.marginTop = currentYpos + 'px'; // re-draw rectangle
}
</script>
</head>
<body>
<div id='rectangle'></div>
<input type="button" value="Right" onclick="moveRectRight()" />
<input type="button" value="Left" onclick="moveRectLeft()" />
<input type="button" value="Up" onclick="moveRectUp()" />
<input type="button" value="Down" onclick="moveRectDown()" />
</body>
</html>
I'm trying to imitate the behavior of CSS border-radius property on a canvas. I've done something which is working, but there are some missing adaptations that the browser is handling, which i can't reproduce on the canvas (See image link below as an example)
However, i'm struggling to adapt the borders when they are getting out of
the shape.
Here is an example, let's take an HTML shape of 100px (Width) X 100px (Height), and then apply the following radius : border-radius: 100px 52px 1px 1px;
Then draw this shape in a canvas with the same parameters.
And then i get this (RED SHAPE = Canvas shape, GREEN SHAPE = HTML shape)
https://imgur.com/a/XGuca
(Sorry i'm not able to upload image, because of my reputation)
I'm using this function to draw the shape
function (xx, yy, ww, hh, rad, fill, stroke) {
if (typeof(rad) === "undefined") rad = 5;
this.beginPath();
this.moveTo(xx, yy);
this.arcTo(xx + ww, yy, xx + ww, yy + hh, rad.tr);
this.arcTo(xx + ww, yy + hh, xx, yy + hh, rad.br);
this.arcTo(xx, yy + hh, xx, yy, rad.bl);
this.arcTo(xx, yy, xx + ww, yy, rad.tl);
if (stroke) this.stroke(); // Default to no stroke
if (fill || typeof(fill) === "undefined") this.fill(); // Default to fill
};
Here is the description of the parameters
xx: X axis position
yy: Y axis position
ww: Width
hh: Height
rad: {tl:0, tr:0, br:0, bl: 0} (For top-left, top-right, bottom-right, bottom-left RADIUS)
I'm not getting what i could do in order to make it working, could someone help me or give me a tip in order to do that ? Thanks !
PS: Sorry for my bad english
(See snippet below)
// Ctx
var ctx = document.getElementById("rounded-rect").getContext("2d");
//Round rect func
ctx.constructor.prototype.fillRoundedRect =
function (xx, yy, ww, hh, rad, fill, stroke) {
if (typeof(rad) === "undefined") rad = 5;
this.beginPath();
this.moveTo(xx, yy);
this.arcTo(xx + ww, yy, xx + ww, yy + hh, rad.tr);
this.arcTo(xx + ww, yy + hh, xx, yy + hh, rad.br);
this.arcTo(xx, yy + hh, xx, yy, rad.bl);
this.arcTo(xx, yy, xx + ww, yy, rad.tl);
if (stroke) this.stroke(); // Default to no stroke
if (fill || typeof(fill) === "undefined") this.fill(); // Default to fill
};
ctx.fillStyle = "red";
ctx.strokeStyle = "#ddf";
var copy = document.getElementById('copy');
var tl = document.getElementById('tl');
var tr = document.getElementById('tr');
var bl = document.getElementById('bl');
var br = document.getElementById('br');
var off = document.getElementById('off');
function test() {
ctx.clearRect(0, 0, 600, 500);
/* 1.Top left */
/* 2. Top right */
/* 3. Bottom right */
/* 4. Bottom left */
var borders = [tl.value, tr.value, br.value, bl.value].join('px ') + 'px';
copy.style.borderRadius = borders;
var copyRad = borders.replace(/px/g, '').split(' ').map(function (a) {
return parseInt(a)
});
var rad = {
tl: copyRad[0],
tr: copyRad[1],
br: copyRad[2],
bl: copyRad[3]
};
var o = +off.value;
ctx.fillRoundedRect(15 + o, 15 + o, 100, 100, rad);
}
tl.oninput = test;
tr.oninput = test;
bl.oninput = test;
br.oninput = test;
off.oninput = test;
test();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html, body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div style="display:inline-block; position: absolute;
left:120px;top:120px; width: 100px; height: 100px; background:green;
border-radius: 10px 5px 10px 20px;" id="copy">
</div>
<canvas style="display: inline-block; position: absolute; zindex:0; left:0; top:0;" id="rounded-rect" width="600" height="500">
</canvas>
<div style="top: 300px; position:absolute; z-index: 1;">
<label>
Top left
<input type="range" min="1" max="100" value="0" class="slider" id="tl"></label><br/>
<label>
Top right
<input type="range" min="1" max="100" value="0" class="slider" id="tr"></label><br/>
<label>
Bottom left
<input type="range" min="1" max="100" value="0" class="slider" id="bl"></label><br/>
<label>
Bottom right
<input type="range" min="1" max="100" value="0" class="slider" id="br"></label><br/>
<label>
Offset
<input type="range" min="1" max="200" value="0" class="slider" id="off"></label><br/>
</div>
</body>
</html>
Seems that the browser somehow corrects the radius if it gets out of the shape. I've created the correctRadius function that does something like this. Of course, the result is not exact the same, but at least the shape doesn't have any gaps.
// Ctx
var ctx = document.getElementById("rounded-rect").getContext("2d");
function correctRadius(r, w, h) {
if (r.tl + r.tr > w) {
r.tl -= (r.tl + r.tr - w) / 2;
r.tr = w - r.tl;
}
if (r.bl + r.br > w) {
r.br -= (r.br + r.bl - w) / 2;
r.bl = w - r.br;
}
if (r.tl + r.bl > h) {
r.tl -= (r.tl + r.bl - h) / 2;
r.bl = h - r.tl;
}
if (r.tr + r.br > h) {
r.tr -= (r.tr + r.br - h) / 2;
r.br = h - r.tr;
}
}
//Round rect func
ctx.constructor.prototype.fillRoundedRect =
function (xx, yy, ww, hh, rad, fill, stroke) {
correctRadius(rad, ww, hh);
if (typeof(rad) === "undefined") rad = 5;
this.beginPath();
this.moveTo(xx, yy);
this.arcTo(xx + ww, yy, xx + ww, yy + hh, rad.tr);
this.arcTo(xx + ww, yy + hh, xx, yy + hh, rad.br);
this.arcTo(xx, yy + hh, xx, yy, rad.bl);
this.arcTo(xx, yy, xx + ww, yy, rad.tl);
if (stroke) this.stroke(); // Default to no stroke
if (fill || typeof(fill) === "undefined") this.fill(); // Default to fill
};
ctx.fillStyle = "red";
ctx.strokeStyle = "#ddf";
var copy = document.getElementById('copy');
var tl = document.getElementById('tl');
var tr = document.getElementById('tr');
var bl = document.getElementById('bl');
var br = document.getElementById('br');
var off = document.getElementById('off');
function test() {
ctx.clearRect(0, 0, 600, 500);
/* 1.Top left */
/* 2. Top right */
/* 3. Bottom right */
/* 4. Bottom left */
var borders = [tl.value, tr.value, br.value, bl.value].join('px ') + 'px';
copy.style.borderRadius = borders;
var copyRad = borders.replace(/px/g, '').split(' ').map(function (a) {
return parseInt(a)
});
var rad = {
tl: copyRad[0],
tr: copyRad[1],
br: copyRad[2],
bl: copyRad[3]
};
var o = +off.value;
ctx.fillRoundedRect(15 + o, 15 + o, 100, 100, rad);
}
tl.oninput = test;
tr.oninput = test;
bl.oninput = test;
br.oninput = test;
off.oninput = test;
test();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html, body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div style="display:inline-block; position: absolute;
left:120px;top:120px; width: 100px; height: 100px; background:green;
border-radius: 10px 5px 10px 20px;" id="copy">
</div>
<canvas style="display: inline-block; position: absolute; zindex:0; left:0; top:0;" id="rounded-rect" width="600" height="500">
</canvas>
<div style="top: 300px; position:absolute; z-index: 1;">
<label>
Top left
<input type="range" min="1" max="100" value="0" class="slider" id="tl"></label><br/>
<label>
Top right
<input type="range" min="1" max="100" value="0" class="slider" id="tr"></label><br/>
<label>
Bottom left
<input type="range" min="1" max="100" value="0" class="slider" id="bl"></label><br/>
<label>
Bottom right
<input type="range" min="1" max="100" value="0" class="slider" id="br"></label><br/>
<label>
Offset
<input type="range" min="1" max="200" value="0" class="slider" id="off"></label><br/>
</div>
</body>
</html>
I am trying to draw quadratic curve on movement of slider. So as slider moves curve will be drawn. I want to do this for quadratic curve and also for bezier curve. This is my code it will work only in chrome
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
.wrapper {
margin: 0 auto;
width: 1000px;
}
.canHdr {
float: left;
width: 450px;
height: 400px;
border: 1px solid red;
}
</style>
</head>
<body>
<form>
<!-- wrapper -->
<div class="wrapper">
<!-- canHdr -->
<div id="canHdr" class="canHdr" >
<p>
This is my 1st div with quadratic curve I want to draw this curve as I move the slider. I want to make it dynamic so when I should be able to change the curve points. Also I want to move an object on that curve as I am doing in my 3rd div.
</p>
<div class="canOuterHdr" >
<canvas id="myCanvas1" width="300" height="195" style="position: relative;">
[No canvas support]
</canvas>
</div>
<div id="slider1" class="newBg">
<input id="slide1" type="range" min="0" max="100" step="1" value="0" onchange="counterSlider('slide1');" />
</div>
</div>
<!--/ canHdr -->
<!-- canHdr2 -->
<div id="canHdr2" class="canHdr" >
<p>
This is my 2nd div. I have bezier curve. I want to make it dynamic so when I should be able to change the curve points. Also I want to move an object on that curve as I am doing in my 3rd div.
</p>
<div class="canOuterHdr" >
<canvas id="myCanvas2" width="300" height="195" style="position: relative;">
[No canvas support]
</canvas>
</div>
<div id="slider2" class="newBg">
<input id="slide2" type="range" min="0" max="100" step="1" value="0" onchange="counterSlider('slide2');" />
</div>
</div>
<!-- canHdr2 -->
</div>
<!-- /wrapper -->
<script type="text/javascript">
// newSprite('myCanvas3', 16, 170);
quadraticCurve('myCanvas1', 18.8, 45, 28, 160, 228, 165);
bezierCurve('myCanvas2', 20, 75, 55.2, 150.0, 200,100, 228, 165)
function counterSlider(sID) {
var slideVal = document.getElementById(sID).value;
/*if (maxValue ==100){
slideVal=slideVal/100;
}*/
slideVal = slideVal / 100;
if (slideVal == 0) {
/* erase('myCanvas2');
erase('myCanvas3');
erase('myCanvas4');*/
//newSprite('myCanvas1b', 18.8, 45);
// newSprite('myCanvas3', 16, 170);
} else if (slideVal > 0 && slideVal <= 34) {
/*erase('myCanvas1');
//erase('myCanvas1b');
erase('myCanvas2');
erase('myCanvas3');
erase('myCanvas4');*/
} else if (slideVal > 34 && slideVal <= 67) {
/*erase('myCanvas1');
erase('myCanvas2');
erase('myCanvas3');
erase('myCanvas4');*/
} else if (slideVal > 67 && slideVal <= 100) {
/*erase('myCanvas1');
erase('myCanvas2');
erase('myCanvas3');
erase('myCanvas4');*/
}
}
function erase(canvasId) {
var canvas = document.getElementById(canvasId);
var context = canvas.getContext("2d");
context.beginPath();
context.clearRect(0, 0, canvas.width, canvas.height);
canvas.width = canvas.width;
}
/**********for backgroundImage********************/
function quadraticCurve(canId, spx, spy, cpx, cpy, endx, endy) {
var canvas = document.getElementById(canId);
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(spx, spy);
ctx.quadraticCurveTo(cpx, cpy, endx, endy);
ctx.strokeStyle = "#eaca2d";
ctx.stroke();
}
function bezierCurve(canId, spx, spy, cpx1, cpy1, cpx2, cpy2, endx, endy) {
var canvas = document.getElementById(canId);
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(spx, spy);
ctx.quadraticCurveTo(cpx1, cpy1, cpx2, cpy2, endx, endy);
ctx.strokeStyle = "#eaca2d";
ctx.stroke();
}
function newSprite(canId, mvx, mvy) {
var canvas = document.getElementById(canId);
var ctx = canvas.getContext('2d');
ctx.globalCompositeOperation = 'source-over';
//ctx.globalCompositeOperation = "destination-over";
ctx.beginPath();
ctx.fillStyle = "#0077c1";
ctx.arc(mvx, mvy, 6, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
</script>
</form>
</body>
</html>
This is the link for jsfiddle: http://jsfiddle.net/Y5yYD/1/
Here’s how to incrementally draw quad & cubic bezier curves with a slider
Example Fiddle: http://jsfiddle.net/m1erickson/auFam/
This function will return an XY point at the specified percentage of a Quad curve:
// quadratic bezier: percent is 0-1
function getQuadraticBezierXY(percent,startPt,controlPt,endPt) {
var x = Math.pow(1-percent,2) * startPt.x + 2 * (1-percent) * percent * controlPt.x + Math.pow(percent,2) * endPt.x;
var y = Math.pow(1-percent,2) * startPt.y + 2 * (1-percent) * percent * controlPt.y + Math.pow(percent,2) * endPt.y;
return( {x:x,y:y} );
}
This function will return an XY point at the specified percentage of a Cubic curve:
// cubic bezier pct is 0-1
function getCubicBezierXY(pct,startPt,controlPt1,controlPt2,endPt){
var x=CubicN(pct,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
var y=CubicN(pct,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
return({x:x,y:y});
}
// cubic formula at percent distance
function CubicN(pct, a,b,c,d) {
var t2 = pct * pct;
var t3 = t2 * pct;
return a + (-a * 3 + pct * (3 * a - a * pct)) * pct
+ (3 * b + pct * (-6 * b + b * 3 * pct)) * pct
+ (c * 3 - c * 3 * pct) * t2
+ d * t3;
}
Here is example code and a Fiddle: http://jsfiddle.net/m1erickson/auFam/
<!doctype html>
<html lang="en">
<head>
<style>
body{ background-color: ivory; }
#wrapper{ position:relative; }
canvas{ position:absolute; left:40px; top:5px; border:1px solid blue;}
#amount{ position:absolute; left:1px; top:5px; margin-bottom:15px; width:23px; border:0; color:#f6931f; font-weight:bold; }
#slider-vertical{ position:absolute; left:5px; top:40px; width:15px; height:225px; border:0px; color:#f6931f; font-weight:bold; }
</style>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script>
$(function() {
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// starting value
var startingSliderValue=50;
drawBoth(startingSliderValue);
$( "#slider-vertical" ).slider({
orientation: "vertical",
range: "min",
min: 0,
max: 100,
value: startingSliderValue,
slide: function( event, ui ) {
$( "#amount" ).val( ui.value );
drawBoth( $("#amount").val() );
}
});
$( "#amount" ).val( $( "#slider-vertical" ).slider( "value" ) );
function drawBoth(sliderValue){
ctx.clearRect(0,0,canvas.width,canvas.height);
drawQuadBezier(sliderValue/100);
drawCubicBezier(sliderValue/100);
}
function drawQuadBezier(pct){
var startPt={ x:18.8, y:45 };
var controlPt={ x:28, y:160};
var endPt={ x:228, y:165 };
ctx.beginPath();
ctx.moveTo(startPt.x,startPt.y);
for(var p=0;p<=pct;p+=.01){
var pt=getQuadraticBezierXY(p,startPt,controlPt,endPt)
ctx.lineTo(pt.x,pt.y);
}
ctx.strokeStyle="green";
ctx.stroke();
var pt=getQuadraticBezierXY(pct,startPt,controlPt,endPt)
drawDot(pt.x,pt.y,"#0077c1");
}
function drawCubicBezier(pct){
var startPt={ x:20, y:75 };
var controlPt1={ x:55.2, y:150};
var controlPt2={ x:200, y:100};
var endPt={ x:228, y:165 };
ctx.beginPath();
ctx.moveTo(startPt.x,startPt.y);
for(var p=0;p<=pct;p+=.01){
var pt=getCubicBezierXY(p,startPt,controlPt1,controlPt2,endPt);
ctx.lineTo(pt.x,pt.y);
}
ctx.strokeStyle="red";
ctx.stroke();
var pt=getCubicBezierXY(pct,startPt,controlPt1,controlPt2,endPt);
drawDot(pt.x,pt.y,"#0077c1");
}
// just draw a dot at xy
function drawDot(x,y,color){
ctx.fillStyle=color;
ctx.beginPath();
ctx.arc(x,y,6,0,Math.PI*2,false);
ctx.closePath();
ctx.fill();
}
// quadratic bezier: percent is 0-1
function getQuadraticBezierXY(percent,startPt,controlPt,endPt) {
var x = Math.pow(1-percent,2) * startPt.x + 2 * (1-percent) * percent * controlPt.x + Math.pow(percent,2) * endPt.x;
var y = Math.pow(1-percent,2) * startPt.y + 2 * (1-percent) * percent * controlPt.y + Math.pow(percent,2) * endPt.y;
return( {x:x,y:y} );
}
// cubic bezier pct is 0-1
function getCubicBezierXY(pct,startPt,controlPt1,controlPt2,endPt){
var x=CubicN(pct,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
var y=CubicN(pct,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
return({x:x,y:y});
}
// cubic formula at percent distance
function CubicN(pct, a,b,c,d) {
var t2 = pct * pct;
var t3 = t2 * pct;
return a + (-a * 3 + pct * (3 * a - a * pct)) * pct
+ (3 * b + pct * (-6 * b + b * 3 * pct)) * pct
+ (c * 3 - c * 3 * pct) * t2
+ d * t3;
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="wrapper">
<input type="text" id="amount" />
<div id="slider-vertical"></div>
<canvas id="canvas" width=300 height=300></canvas>
</div>
</body>
</html>
Hi I want to draw a curve as I move slider. I have two kinds of curves. Bezier curve and quadratic cruve. Also As I draw the curve I want to move an object on that same path. I want it to be dynamic so If I should be able to change the curve points.
So I need a function which I can call on the slider change as I am doing for line.
Here is my code. This code will work only in chrome.
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
.wrapper {
margin: 0 auto;
width: 1000px;
}
.canHdr {
float: left;
width: 450px;
height: 400px;
border: 1px solid red;
}
</style>
</head>
<body>
<form>
<!-- wrapper -->
<div class="wrapper">
<!-- canHdr -->
<div id="canHdr" class="canHdr" >
<p>
This is my 1st div with quadratic curve I want to draw this curve as I move the slider. I want to make it dynamic so when I should be able to change the curve points. Also I want to move an object on that curve as I am doing in my 3rd div.
</p>
<div class="canOuterHdr" >
<canvas id="myCanvas1" width="300" height="195" style="position: relative;">
[No canvas support]
</canvas>
</div>
<div id="slider1" class="newBg">
<input id="slide1" type="range" min="0" max="100" step="1" value="0" onchange="counterSlider('slide1');" />
</div>
</div>
<!--/ canHdr -->
<!-- canHdr2 -->
<div id="canHdr2" class="canHdr" >
<p>
This is my 2nd div. I have bezier curve. I want to make it dynamic so when I should be able to change the curve points. Also I want to move an object on that curve as I am doing in my 3rd div.
</p>
<div class="canOuterHdr" >
<canvas id="myCanvas2" width="300" height="195" style="position: relative;">
[No canvas support]
</canvas>
</div>
<div id="slider2" class="newBg">
<input id="slide2" type="range" min="0" max="100" step="1" value="0" onchange="counterSlider('slide2');" />
</div>
</div>
<!-- canHdr2 -->
<!-- canHdr3 -->
<div id="canHdr3" class="canHdr" >
<p>
This is my 3rd div with slanting line. I want to move a ball on this line when I move the slider. So as the line increases ball will also move on the line.
</p>
<div class="canOuterHdr" >
<canvas id="myCanvas3" width="300" height="195" style="position: relative;">
[No canvas support]
</canvas>
</div>
<div id="slider3" class="newBg">
<input id="slide3" type="range" min="0" max="100" step="1" value="0" onchange=" drawSlopeCurve2('slide3','100'); " />
</div>
</div>
<!--/ canHdr3 -->
<!-- canHdr4 -->
<div id="canHdr4" class="canHdr" >
<p>
This is my 4th div with slanting line. I want to move a ball on this line when I move the slider. So as the line increases ball will also move on the line.
</p>
<div class="canOuterHdr" >
<canvas id="myCanvas4" width="300" height="195" style="position: relative;">
[No canvas support]
</canvas>
</div>
<div id="slider4" class="newBg">
<input id="slide4" type="range" min="0" max="100" step="1" value="0" onchange=" drawSlopeCurve1('slide4','100'); " />
</div>
</div>
<!--/ canHdr4 -->
</div>
<!-- /wrapper -->
<script type="text/javascript">
newSprite('myCanvas3', 16, 170);
quadraticCurve('myCanvas1', 18.8, 45, 28, 160, 228, 165);
bezierCurve('myCanvas2', 20, 75, 55.2, 150.0, 200,100, 228, 165)
function counterSlider(sID) {
var slideVal = document.getElementById(sID).value;
/*if (maxValue ==100){
slideVal=slideVal/100;
}*/
slideVal = slideVal / 100;
if (slideVal == 0) {
/* erase('myCanvas2');
erase('myCanvas3');
erase('myCanvas4');*/
//newSprite('myCanvas1b', 18.8, 45);
newSprite('myCanvas3', 16, 170);
} else if (slideVal > 0 && slideVal <= 34) {
/*erase('myCanvas1');
//erase('myCanvas1b');
erase('myCanvas2');
erase('myCanvas3');
erase('myCanvas4');*/
} else if (slideVal > 34 && slideVal <= 67) {
/*erase('myCanvas1');
erase('myCanvas2');
erase('myCanvas3');
erase('myCanvas4');*/
} else if (slideVal > 67 && slideVal <= 100) {
/*erase('myCanvas1');
erase('myCanvas2');
erase('myCanvas3');
erase('myCanvas4');*/
}
}
function erase(canvasId) {
var canvas = document.getElementById(canvasId);
var context = canvas.getContext("2d");
context.beginPath();
context.clearRect(0, 0, canvas.width, canvas.height);
canvas.width = canvas.width;
}
/**********for backgroundImage********************/
function quadraticCurve(canId, spx, spy, cpx, cpy, endx, endy) {
var canvas = document.getElementById(canId);
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(spx, spy);
ctx.quadraticCurveTo(cpx, cpy, endx, endy);
ctx.strokeStyle = "#eaca2d";
ctx.stroke();
}
function bezierCurve(canId, spx, spy, cpx1, cpy1, cpx2, cpy2, endx, endy) {
var canvas = document.getElementById(canId);
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(spx, spy);
ctx.quadraticCurveTo(cpx1, cpy1, cpx2, cpy2, endx, endy);
ctx.strokeStyle = "#eaca2d";
ctx.stroke();
}
function newSprite(canId, mvx, mvy) {
var canvas = document.getElementById(canId);
var ctx = canvas.getContext('2d');
ctx.globalCompositeOperation = 'source-over';
//ctx.globalCompositeOperation = "destination-over";
ctx.beginPath();
ctx.fillStyle = "#0077c1";
ctx.arc(mvx, mvy, 6, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
function drawSlopeCurve1(sID, maxValue) {
// erase('canvasTwo');
var canId = 'myCanvas4';
var slideVal = parseInt(document.getElementById(sID).value);
var canvas = document.getElementById(canId);
var context = canvas.getContext('2d');
canvas.width = canvas.width;
//line end points
x1 = 16;
y1 = 170;
x2 = 200;
y2 = 80;
//get slope (rise over run)
var m = (y2 - y1) / (x2 - x1);
//get y-intercept
var b = y1 - (m * x1);
//get distance between the two points
var distance = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
//get new x and y values
var x = x1 + parseInt(distance / maxValue * slideVal);
var y = parseInt(m * x + b);
context.beginPath();
context.moveTo(x1, y1);
context.lineTo(x, y);
context.lineWidth = 0.6;
context.stroke();
newSprite(canId, x, y);
}
function drawSlopeCurve2(sID, maxValue) {
// erase('canvasTwo');
var canId = 'myCanvas3';
var slideVal = parseInt(document.getElementById(sID).value);
var canvas = document.getElementById(canId);
var context = canvas.getContext('2d');
canvas.width = canvas.width;
//line end points
x1 = 16;
y1 = 170;
x2 = 160;
y2 = 72;
//get slope (rise over run)
var m = (y2 - y1) / (x2 - x1);
//get y-intercept
var b = y1 - (m * x1);
//get distance between the two points
var distance = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
//get new x and y values
var x = x1 + parseInt(distance / maxValue * slideVal);
var y = parseInt(m * x + b);
context.beginPath();
context.moveTo(x1, y1);
context.lineTo(x, y);
context.lineWidth = 0.6;
context.stroke();
newSprite(canId, x, y);
}
</script>
</form>
</body>
</html>
This is link for jsfiddle: http://jsfiddle.net/QRVxH/
You should begin by defining the curve in a function, so you can calculate where the graph should end for each x-position. Then you also know where to draw the end-dot.
My demo function has a function to draw a sine on the canvas:
function calc(x){
var y = 100 + ( 50*Math.sin(x*400));
return y;
}
By drawing a line (not a curve!) between the points you get your graph.
for (var x=0; x<=400 && (x <= slider.value); x+=3){
y= calc(x);
ctx.lineTo(x, y);
}
Working demo: http://jsfiddle.net/w1ll3m/CbjWK/11/
Added html5slider.js to make the slider work in firefox.
Right now i have a form where i can enter some text and it appears in a canvas element,
however when i press backspace the text doesn't go away anymore and when i retype text it appears on top of the old text.
Is there a way to get the canvas element to respond to deleting text also?
<!DOCTYPE html>
<html>
<title>dropIn Print Generator</title>
<body>
<h1>dropIn Print Generator</h1>
<form method="post" action="run.php">
<p>brand name
<input type="text" id="brand" onkeyup="showBrand(this.value)" /></p>
<p>product name
<input type="text" id="product" onkeyup="showProductName(this.value)" /></p>
<p>product details
<input type="text" id="details" onkeyup="showProductDetail(this.value)" /></p>
<p>product sku
<input type="text" id="sku" /></p>
<p>product image
<input type="file" id="image" /></p>
</form>
<canvas id="mainCanvas" width="400" height="600" style="border:1px solid #000000;"></canvas>
<script>
var canvas = document.getElementById('mainCanvas');
var context = canvas.getContext('2d');
// begin upper shape
context.beginPath();
context.moveTo(0, 0);
context.lineTo(400, 0);
context.lineTo(400, 300);
context.lineTo(380, 30);
context.lineTo(0, 50);
context.lineTo(0, 0);
// complete upper shape
context.closePath();
context.lineWidth = 1;
context.strokeStyle = 'black';
context.fillStyle = 'black';
context.fill();
context.stroke();
// begin bottom shape
context.beginPath();
context.moveTo(400, 600);
context.lineTo(200, 600);
context.lineTo(400, 585);
context.lineTo(400, 600);
// complete bottom shape
context.closePath();
context.lineWidth = 1;
context.strokeStyle = 'black';
context.fillStyle = 'black';
context.fill();
context.stroke();
function showBrand(str){
context.fillStyle = 'black';
context.font = '20px sans-serif';
context.textBaseline = 'bottom';
context.fillText(str, 30, 100);
}
function showProductName(str){
context.fillStyle = 'black';
context.font = '30px sans-serif';
context.textBaseline = 'bottom';
context.fillText(str, 30, 135);
}
function showProductDetail(str){
context.fillStyle = 'black';
context.font = '20px sans-serif';
context.textBaseline = 'bottom';
context.fillText(str, 30, 160);
}
</script>
</body>
</html>
You need to clear the canvas before each time you paint some new text onto it, otherwise anything you've already drawn on the canvas will remain and you'll be drawing on top of it.
function clearCanvas() {
// Redraw the background color over the top of the old text to 'clear' it.
context.fillStyle = '#fff';
context.fillRect(0, 0, canvas.width, canvas.height);
}
Add a call to this function to the start of your other 3 drawing functions.