HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URLs added here will be added as <link>
s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import
statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by Skypack, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ES6 import
usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<!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>01 - Canvas - Basics</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<canvas id="canvas"></canvas>
<script src="main.js"></script>
</body>
</html>
html, body {
margin: 0;
padding: 0;
}
#canvas {
position: absolute;
left: 100px;
top: 100px;
}
// alert("het werkt")
let cvs = document.getElementById('canvas');
let winHeight = window.innerHeight;
let winWidth = window.innerWidth;
cvs.style.backgroundColor = "#FF8";
// cvs.style.left = "100px";
// cvs.style.top = "100px";
cvs.width = 700; //winWidth - 200;
cvs.height = 700; //winHeight - 200;
cvs.style.border = '3px solid red';
cvs.style.overflow = 'none';
/*
To create objects on the canvas the CONTEXT is essential
*/
let ctx = cvs.getContext('2d');
/*
Make canvas dimensions variable
*/
let cvsWidth = cvs.width;
let cvsHeight = cvs.height;
/*
take margins and paddings of the canvas into account as
offsets
*/
let offsetX, offsetY;
getOffset = () => {
let cvsOffsets = cvs.getBoundingClientRect();
offsetX = cvsOffsets.left;
offsetY = cvsOffsets.top;
}
getOffset();
window.onscroll = () => {getOffset();}
window.onresize = () => {getOffset();}
cvs.onresize = () => {getOffset();}
let shapes = [];
let curShapeIdx = null;
let isDragging = false;
let srtX, srtY;
/*
We push new shapes into this array by pushing a JS object
with some attributes we see fit.
Blue is the last one drawn; it get's on top.
*/
shapes.push({ x: 200, y: 50, width: 200, height: 200, color: 'red'});
shapes.push({ x: 20, y: 20, width: 100, height: 100, color: 'blue'});
/*
Detect edge collision
*/
edgeCollision = (shape, cvs) => {
let lefCol = (shape.x < 15);
let rigCol = ((shape.x + shape.width) > (cvs.width - 15));
let topCol = (shape.y < 15);
let botCol = ((shape.y + shape.height) > (cvs.height - 15));
return (lefCol || rigCol || topCol || botCol);
}
/*
Draw these shapes onto the canvas.
Define functions before calling them. !IMPORTANT
*/
drawShapes = () => {
// this will remove all drawings from entire canvas
ctx.clearRect(3, 3, cvsWidth, cvsHeight);
for(let shape of shapes) {
ctx.fillStyle = shape.color;
// if (!edgeCollision(shape, cvs)) {
// ctx.clearRect(3, 3, cvsWidth, cvsHeight);
// ctx.fillRect(shape.x, shape.y, shape.width, shape.height);
// }
if (shape.x < 15) { shape.x = 15; }
if ((shape.x + shape.width) > (cvs.width - 15)) {
shape.x = cvs.width - shape.width - 15;
}
if (shape.y < 15) { shape.y = 15; }
if ((shape.y + shape.height) > (cvs.height - 15)) {
shape.y = cvs.height - shape.height - 15;
}
ctx.fillRect(shape.x, shape.y, shape.width, shape.height);
}
}
drawShapes();
/*
Program mouse handle functionality.
In these mouse functions we'll change the x- and y-coordinates
of the shapes.
*
mouseInShape detects whether the cursor is inside the shape on
a mouseDown event. This is just a handy custom function that
has notthing to do with mouse events.
*/
let mouseInShape = function(x, y, shape) {
let sLeft = shape.x;
let sRight = shape.x + shape.width;
let sTop = shape.y;
let sBottom = shape.y + shape.height;
return (x > sLeft && x < sRight && y > sTop && y < sBottom)
}
/*
mouseDown is a real event. It triggers the event when we press
the left mouse button.
We NEED to register the events AFTER we define the function!
*/
let mouseDown = (e) => {
// Tell the browser that we do our own things.
e.preventDefault();
// console.log(e);
// parseInt() makes sure we have a number to work with.
srtX = parseInt(e.clientX - offsetX);
srtY = parseInt(e.clientY - offsetY);
// console.log(srtX,'*',srtY)
/*
detect whether we mouse down on one of the shapes.
curShapeIdx is a global var that holds the index of the
shape we've currently clicked upon.
*/
let index = 0;
for (let shape of shapes) {
if (ctx.isPointInPath(srtX, srtY)) {
console.log("point in path");
}
if (mouseInShape(srtX, srtY, shape)) {
/*
The last shape drawn get's 'on top';
*/
console.log("In shape with index: ", index, shape.color);
curShapeIdx = index;
/*
isDragging sets the currently clicked shape to a
state where it's 'draggable'. It's not yet in the
process of being dragged, that's happening through
mouseMove().
*/
isDragging = true; // isDraggable
/*
return is !IMPORTANT because we want only 'select'
and move the currently clicked upon shape.
*/
return;
}
index++;
}
} // end mouseDown() ---------------------------------
let mouseUp = (e) => {
if (!isDragging) {
/*
When we're not in dragging mode we return
*/
return;
}
e.preventDefault();
/*
When we lift the mouse button this event is triggered
and when we're in dragging mode, we stop draggability.
*/
isDragging = false;
}
let mouseOut = (e) => {
if (!isDragging) {
return;
}
e.preventDefault();
isDragging = false;
}
/*
mouseMove() is triggered on EACH and EVERY movement of the
mouse, independent of whether there's an object 'under' the
mouse the be dragged or not.
It just keeps generating mouse coordinates all the time.
*/
let mouseMove = (e) => {
if (!isDragging) {
/*
When we're not dragging we're not conserned with the
generated mouse coordinates.
*/
return;
} else {
e.preventDefault();
/*
get the currently generated mouse coordinates.
*/
let curX = parseInt(e.clientX - offsetX);
let curY = parseInt(e.clientY - offsetY);
/*
calculate the distance between the mouseDown position
and the currently generated mouse coordinates.
*/
let dX = curX - srtX;
let dY = curY - srtY;
/*
get the currently selected shape
*/
let currentShape = shapes[curShapeIdx];
/*
update the currently selected shape's position.
Here we can take the shape's width and height into account
to prevent it from running off the canvas.
*/
currentShape.x += dX;
currentShape.y += dY;
/*
clear the canvas - this deletes the old shape - and draw
the shape on it's new position.
*/
drawShapes();
/*
store the current mouse position so we can use
that on the next moved mouse position.
*/
srtX = curX;
srtY = curY;
}
}
// https://www.youtube.com/watch?v=7PYvx8u_9Sk&list=PLN0tvDAN1yvSNbkHAwPzJ5O4pP_e2vyme&index=11
/*
register mouse events THE ORDER IS IMPORTANT!
function FIRST then register.
*/
cvs.onmousedown = mouseDown;
cvs.onmouseup = mouseUp;
cvs.onmouseout = mouseOut;
cvs.onmousemove = mouseMove;
Also see: Tab Triggers