How to disable text wrapping when viewport border is reached? - html

Consider code snippet below (you can click and drag outside the text) - the text is wrapping when viewport border is reached.
let isCaptureActive = false;
let offset = {
x: 0,
y: 0
}
const fooDOM = document.querySelector('#foo');
const bodyDOM = document.body;
window.addEventListener('mousemove', e => {
if(!isCaptureActive) return;
offset.x += e.movementX;
offset.y += e.movementY;
fooDOM.style.left = offset.x + 'px';
fooDOM.style.top = offset.y + 'px';
});
window.addEventListener('mousedown', e => {
if(e.target !== fooDOM) isCaptureActive = true;
});
window.addEventListener('mouseup', e => {
isCaptureActive = false;
});
#foo {
position: absolute;
background-color: wheat;
min-width: 250px;
max-width: 500px;
}
<div id="foo">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras porta nisl justo, id rutrum lorem cursus in. Nullam dictum lobortis lorem, vitae facilisis lectus. Donec ut eros lacinia, suscipit nisl ut, convallis diam.
</div>
How to make text ignore viewport border like it's not even there?
EDIT: I need to be able to set the element's min-width and max-width attributes.

let isCaptureActive = false;
let offset = {
x: 0,
y: 0
}
const fooDOM = document.querySelector('#foo');
const bodyDOM = document.body;
window.addEventListener('mousemove', e => {
if(!isCaptureActive) return;
offset.x += e.movementX;
offset.y += e.movementY;
fooDOM.style.left = offset.x + 'px';
fooDOM.style.top = offset.y + 'px';
});
window.addEventListener('mousedown', e => {
if(e.target !== fooDOM) isCaptureActive = true;
});
window.addEventListener('mouseup', e => {
isCaptureActive = false;
});
#foo {
position: absolute;
background-color: wheat;
min-width: 250px;
max-width: 500px;
}
#pg {
width: 100vw;
}
<div id="foo">
<p id='pg'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras porta nisl justo, id rutrum lorem cursus in. Nullam dictum lobortis lorem, vitae facilisis lectus. Donec ut eros lacinia, suscipit nisl ut, convallis diam.
</p>
</div>
I simply wrapped the text inside a <p> element and set its width to 100vw.

Related

componentDidMount in React and the real DOM

I am trying to get the height on an element.
I want the parent div to adjust its height to the first paragraph of its children paragraph elements. Then a "Read More"/"Read Less" button expands the parent div to reveal all paragraphs or shrinks to only one paragraph.
I have experimented with useEffect, useLayoutEffect and componentDidMount in a class component and they all seem to need a setTimeout delay for the parent div to attain the perfect height.
Sorry if my code is fuzzy. I am new to React. :)
TIA
import styled from 'styled-components'
import React, { useRef, useLayoutEffect, useState } from 'react'
const CatIntroStyled = styled.div`
width: 1000px;
margin: 0 auto;
button{
display: block;
margin: 0 auto;
background: none;
}
button:focus{
outline: none;
}
`
const IntroText = styled.div`
height: ${({introStyle})=>{
if(introStyle.initIntroHeight === "auto") return "auto"
return introStyle.introExpanded ? introStyle.initIntroHeight+"px": introStyle.initFirstPara+"px";
}};
overflow: hidden;
transition: all 1s;
margin-bottom: 2rem
`
const formatIntro = (text, paraRef)=>{
let formatedText = text.replace(/<[^>]*>?/gm, "").replace(/\n\r/g, "")
let returnText = formatedText.split("\r\n").map((paragraph, key) => {
if(key===0) return <p ref={paraRef} key={key}>{paragraph}</p>;
return <p key={key}>{paragraph}</p>
})
return returnText
}
const CatIntro = ({title, text})=>{
const firstIntroPara = useRef();
const introRef = useRef();
const [intro, setIntro] = useState({
initFirstPara: 0,
initIntroHeight: "auto",
introExpanded: false
})
useLayoutEffect(()=>{
setTimeout(()=>{
setIntro({
...intro,
initIntroHeight: introRef.current.offsetHeight,
initFirstPara: firstIntroPara.current.offsetHeight,
})
}, 1000)
}, [])
return(
<CatIntroStyled>
<h1 className="globalTitleStyle">{title}</h1>
<IntroText ref={introRef} introStyle={intro}>
{formatIntro(text, firstIntroPara)}
</IntroText>
<button onClick={(e)=>{
setIntro({
...intro,
introExpanded: !intro.introExpanded
})
}}>{ intro.introExpanded ? "READ LESS": "READ MORE" }</button>
</CatIntroStyled>
)
}
export default CatIntro
Is there a more robust way of knowing when elements are truly painted on the screen?
TIA
Try using useLayoutEffect.
This runs synchronously immediately after React has performed all DOM mutations. This can be useful if you need to make DOM measurements (like getting the scroll position or other styles for an element).
Example
function App() {
const divRef = React.useRef(null);
React.useLayoutEffect(() => {
console.log(divRef.current.clientHeight)
}, [])
return (
<div ref={divRef} style={{ height: 100, width: 100, backgroundColor: 'red' }}/>
);
}
For this :- You need to change your class component to functional ones.
Maybe i don't fully understand why you need the height.
But if each child of the component is a paragraph, and you either want to show all the paragraphs when expanded, but only one paragraph when not expanded, you could do something like this:
import React, { useState } from "react";
export default function Expandable({ children, initial = false }) {
const [expanded, setExpanded] = useState(initial);
return (
<div>
{expanded ? children : [...children].slice(0,1)}
<button onClick={() => setExpanded(!expanded)}>{`Read ${
expanded ? "less" : "more"
}`}</button>
</div>
);
}
Then you could consume the component like this:
<Expandable>
<p>
egestas ultrices. Curabitur eget lorem eu augue pretium blandit at non
metus. Mauris a venenatis tellus, vel mollis leo. Vivamus nec
elementum neque, non mollis felis.
</p>
<p>
fringilla. Sed convallis sem sed diam vehicula egestas. In tincidunt
hendrerit elit, eu facilisis leo vulputate id. Sed rutrum imperdiet
convallis. Nam mi magna, lacinia vitae consequat vel, consequat eget
ex. Maecenas nec ex egestas, mattis orci sit amet, dictum sem. Sed id
tincidunt felis. Vivamus ipsum erat, sagittis sed consequat et,
molestie a risus. Quisque nec risus fringilla, pellentesque leo a,
venenatis leo.
</p>
<p>
est in varius pulvinar. Ut dignissim condimentum semper. Vestibulum
blandit purus vitae dapibus finibus. Nam iaculis metus orci, et
posuere lectus imperdiet at. Suspendisse non erat tortor.
</p>
<p>ullamcorper sagittis.</p>
</Expandable>
Edit:
You can get the height of the first paragraph like this.
Note: with this approach, you probably need to listen for a resize event and adjust the value of the height state.
import React, { useState, useEffect, useRef } from "react";
export default function Expandable({ children, initial = false }) {
const [expanded, setExpanded] = useState(initial);
const [firstParagraphHeight, setFirstParagraphHeight] = useState(0);
const ref = useRef(null);
useEffect(() => {
const height = ref.current.children[0].getBoundingClientRect().height;
setFirstParagraphHeight(height);
}, []);
return (
<>
<div
ref={ref}
style={{
overflow: "hidden",
maxHeight: expanded ? "none" : `${firstParagraphHeight}px`
}}
>
{children}
</div>
<button onClick={() => setExpanded(!expanded)}>{`Read ${
expanded ? "less" : "more"
}`}</button>
</>
);
}

JQuery Stop Text Flickering when Pressing Show Less / Show More

I have a number of user stories on my website page. I don't want to show the entirety of each story if the user doesn't want to read it, so I show the first 2 lines and there is a Show more link to press to see the whole story. The user can then press the link again to See less. The issue comes when the user clicks the Show less link, the story condenses and shows 2 lines, but there is a momentary flicker of say 2 additional lines (can't quite make it out as its there for a few milliseconds). And it is this that I don't want.
This is my HTML and jQuery which is loaded via Ajax Request.
$(document).ready(function() {
$(".content").on("click", ".showMore a", function() {
var $this = $(this);
var content = $this.parent().prev()
var linkText = $this.text().toUpperCase();
if (linkText === "SHOW MORE") {
linkText = "Show less";
content.switchClass("hideContent", "showContent", 400);
} else {
linkText = "Show more";
content.switchClass("showContent", "hideContent", 400);
}
$this.text(linkText);
});
});
.hideContent {
overflow: hidden;
line-height: 1em;
height: 4em;
}
.showContent {
line-height: 1em;
height: auto;
}
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="hideContent" style="">
<div class="post-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In id erat pharetra risus fermentum aliquam. Maecenas eu nisi posuere, rutrum orci et, imperdiet elit. Nulla tempor imperdiet sagittis. Aenean cursus justo ac enim lacinia vehicula. Etiam dictum
suscipit nibh, at iaculis velit lobortis vel. Duis pretium diam ut lectus mollis vehicula.</div>
<div class="post-action"><input type="button" value="Like" id="like_94" class="like"><span class="likesTotal" id="likes_94">0</span>
</div>
</div>
<div class="showMore"><a>Show more</a></div>
</div>
</div>
I hope that's what you wanted. You can do this easily by using .addClass and .removeClass
Also. if you content and stories display as exactly as the example in question then .parent() is not what you want you can call .prev() and it will work just find.
Simple Show and Hide
Using addClass and removeClass
Working Demo: https://jsfiddle.net/usmanmunir/cks8d067/
Run snippet below to see it working.
$(document).ready(function() {
$(".showMore").on("click", function() {
var $this = $(this);
var content = $this.prev()
var linkText = $this.text().toUpperCase();
if (linkText === "SHOW MORE") {
linkText = "Show less";
content.addClass("showContent").removeClass("hideContent");
} else {
content.addClass("hideContent").removeClass("showContent");
linkText = "Show more";
}
$this.text(linkText);
});
});
.hideContent {
overflow: hidden;
line-height: 1em;
height: 2em;
}
.showContent {
line-height: 1em;
height: auto;
}
.showMore {
cursor: pointer;
}
<div class="hideContent">
<div class="post-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In id erat pharetra risus fermentum aliquam. Maecenas eu nisi posuere, rutrum orci et, imperdiet elit. Nulla tempor imperdiet sagittis. Aenean cursus justo ac enim lacinia vehicula. Etiam dictum
suscipit nibh, at iaculis velit lobortis vel. Duis pretium diam ut lectus mollis vehicula.</div>
<div class="post-action"><input type="button" value="Like" id="like_94" class="like"><span class="likesTotal" id="likes_94">0</span>
</div>
</div>
<div class="showMore"><a>Show more</a></div>
Accordion Effects
Using accordion effect we can use .animate and .css
To do the accordion effects we can use .animate and .css for height to show more or less of the story. We will use .siblings
Working Fiddle: https://jsfiddle.net/usmanmunir/ovgah34z/
$(document).ready(function() {
$(".content").on("click", '.showMore', function() {
var $this = $(this);
var content = $this.prev()
var linkText = $this.text().toUpperCase();
if (linkText === "SHOW MORE") {
linkText = "Show less";
$this.siblings('div').css('height', 'auto');
var currHeight = $this.siblings('div').height();
$this.siblings('div').css('height', '2em');
$this.siblings('div').animate({
height: currHeight
}, 500);
} else {
$this.siblings('div').animate({
height: '2em'
}, 500);
linkText = "Show more";
}
$this.text(linkText);
});
});
.hideContent {
overflow: hidden;
line-height: 1em;
height: 2em;
}
.showContent {
line-height: 1em;
height: auto;
}
.showMore {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="hideContent">
<div class="post-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In id erat pharetra risus fermentum aliquam. Maecenas eu nisi posuere, rutrum orci et, imperdiet elit. Nulla tempor imperdiet sagittis. Aenean cursus justo ac enim lacinia vehicula. Etiam dictum
suscipit nibh, at iaculis velit lobortis vel. Duis pretium diam ut lectus mollis vehicula.</div>
<div class="post-action"><input type="button" value="Like" id="like_94" class="like"><span class="likesTotal" id="likes_94">0</span>
</div>
</div>
<div class="showMore"><a>Show more</a></div>
</div>
Let me know.
Here is an example of toggle inside a custom function .
If this is the result that you want .
Do not forget to mark my answer as the right answer!
Regards
function makeTheMagic(){
$("#extraContent").toggle();
let btnText= $("#btnAction").text() == "Show More!"?"Show Less!":"Show More!";
$("#btnAction").text(btnText);
}
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='card'>
<div class='card-body'>
<p class='alert-success'>
In my situation I want to show the first 2 sentences and then show the rest of the text with a toggle, but I couldn't find any examples of this. Did you have any examples of this? Thank you.
</p>
<p class='alert-danger' style='display:none' id='extraContent'>
I have a number of user stories on my website page. I don't want to show the entirety of each story if the user doesn't want to read it, so I show the first 2 lines and there is a Show more link to press to see the whole story. The user can then press the link again to See less. The issue comes when the user clicks the Show less link, the story condenses and shows 2 lines, but there is a momentary flicker of say 2 additional lines (can't quite make it out as its there for a few milliseconds). And it is this that I don't want.
</p>
<span class='btn btn-outline-success' onclick='makeTheMagic()' id='btnAction'>Show More!</span>
</div>
</div>

CSS has-scrollbar selector? Target elements with visible scrollbars only

I want to target elements which have a visible scrollbar using only CSS. Is this possible without javascript?
For example, If I have 3 divs styled with overflow-y:auto, How do I change the styles for them only when their scrollbar has appeared?
CSS does not cover this selection. You need to use JavaScript.
With pure CSS I doubt it but it doesn't require a lot of javascript code either, look at this example:
document.querySelectorAll('*').forEach(el => {
if (el.offsetHeight > document.documentElement.offsetHeight) {
console.log('I am higher than my father: ', el);
el.classList.add('higher-class');
}
});
.higher-class {
color: red;
}
<div class="container" style="height:50px;">
<div class="some-child" style="height:100px;font-size: 5rem">
Higher element
</div>
</div>
check
offsetHeight property:
https://developer.mozilla.org/es/docs/Web/API/HTMLElement/offsetHeight
And the classList property:
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
It's not possible without javascript
However it only requires a single line of JS to toggle a CSS class on when the scrollbar is visible:
el.classList.toggle("scrollbarOn", el.scrollHeight > el.clientHeight)
Here's a demo:
//toggles a class on an element when the scrollbar is visible:
function updScrollClass(el) {
return el.classList.toggle("scrollbarOn", el.scrollHeight > el.clientHeight)
}
//changes the height of myDiv every second:
setInterval(function(){
var myDiv = document.getElementById('myDiv')
myDiv.classList.toggle('tall')
updScrollClass(myDiv)
},1000)
#myDiv{
width:150px;
height:200px;
overflow:auto;
}
#myDiv.tall{
height:300px;
}
.scrollbarOn{
background:yellow;
}
<div id='myDiv' class='tall'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc convallis nisl in accumsan porta. Etiam in urna orci. Vestibulum elementum, velit ac vestibulum efficitur, est elit auctor massa, nec porta ante nunc eget tellus. Integer eu ligula felis.
</div>

On-click behavior of buttons in html

I have a CSS script which has 5 buttons.
Clicking the first button should display a text on the same page in a fixed region (maybe by using frames or writing a hidden function and then doing show()).
If the second button is clicked, some other text should appear in the earlier region. Similarly for other buttons. What would be the most efficient way of doing this? (Achieving the fastest loading of the page).
Try this:
HTML
<div id="textcontainer"></div>
<button id="button1" onclick="setText(0);">Button 1</button>
<button id="button2" onclick="setText(1);">Button 2</button>
<button id="button3" onclick="setText(2);">Button 3</button>
<button id="button4" onclick="setText(3);">Button 4</button>
<button id="button5" onclick="setText(4);">Button 5</button>
Javascript:
var text = [
'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.',
'Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.',
'Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.',
'Aenean nec lorem. In porttitor. Donec laoreet nonummy augue.',
'Suspendisse dui purus, scelerisque at, vulputate vitae, pretium mattis, nunc. Mauris eget neque at sem venenatis eleifend. Ut nonummy.'
];
function setText(index){
var box = document.getElementById('textcontainer');
box.innerHTML = text[index];
}
You can see this in action at: http://jsfiddle.net/Wnw7X/
I guess this?
<iframe name="content"></iframe>
Button 1
Button 2
And so on...
Then add some CSS to make them look like buttons (border, background, etc)
ok, here is a complete demo - copy all the code and paste your editor. and run.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript">
window.onload = function() {
var myArray = ['you click the first button', 'you click the second button', 'you click the third button', 'you click the fourth button', 'you click the fifth button'];
var one = document.getElementById('buttonOne');
var two = document.getElementById('buttonTwo');
var three = document.getElementById('buttonThree');
var four = document.getElementById('buttonFour');
var five = document.getElementById('buttonFive');
one.onclick = clickHandler;
two.onclick = clickHandler;
three.onclick = clickHandler;
four.onclick = clickHandler;
five.onclick = clickHandler;
function clickHandler(evt) {
//console.log(evt.target.id);
var header = document.getElementsByTagName('h1')[0];
if(evt.target.id === 'buttonOne') {
header.innerHTML = myArray[0];
console.log(myArray[0]);
console.log('click');
}
else if (evt.target.id === 'buttonTwo') {
header.innerHTML = myArray[1];
}
else if (evt.target.id === 'buttonThree') {
header.innerHTML = myArray[2];
}
else if (evt.target.id === 'buttonFour') {
header.innerHTML = myArray[3];
}
else if (evt.target.id === 'buttonFive') {
header.innerHTML = myArray[4];
}
}
}
</script>
</head>
<body>
<button id="buttonOne">One</button>
<button id="buttonTwo">Two</button>
<button id="buttonThree">Three</button>
<button id="buttonFour">Four</button>
<button id="buttonFive">Five</button>
<h1> </h1>
</body>
</html>

Canvas width and height in HTML5

Is it possible to fix the width and height of an HTML5 canvas element?
The usual way is the following :
<canvas id="canvas" width="300" height="300"></canvas>
The canvas DOM element has .height and .width properties that correspond to the height="…" and width="…" attributes. Set them to numeric values in JavaScript code to resize your canvas. For example:
var canvas = document.getElementsByTagName('canvas')[0];
canvas.width = 800;
canvas.height = 600;
Note that this clears the canvas, though you should follow with ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height); to handle those browsers that don't fully clear the canvas. You'll need to redraw of any content you wanted displayed after the size change.
Note further that the height and width are the logical canvas dimensions used for drawing and are different from the style.height and style.width CSS attributes. If you don't set the CSS attributes, the intrinsic size of the canvas will be used as its display size; if you do set the CSS attributes, and they differ from the canvas dimensions, your content will be scaled in the browser. For example:
// Make a canvas that has a blurry pixelated zoom-in
// with each canvas pixel drawn showing as roughly 2x2 on screen
canvas.width = 400;
canvas.height = 300;
canvas.style.width = '800px';
canvas.style.height = '600px';
See this live example of a canvas that is zoomed in by 4x.
var c = document.getElementsByTagName('canvas')[0];
var ctx = c.getContext('2d');
ctx.lineWidth = 1;
ctx.strokeStyle = '#f00';
ctx.fillStyle = '#eff';
ctx.fillRect( 10.5, 10.5, 20, 20 );
ctx.strokeRect( 10.5, 10.5, 20, 20 );
ctx.fillRect( 40, 10.5, 20, 20 );
ctx.strokeRect( 40, 10.5, 20, 20 );
ctx.fillRect( 70, 10, 20, 20 );
ctx.strokeRect( 70, 10, 20, 20 );
ctx.strokeStyle = '#fff';
ctx.strokeRect( 10.5, 10.5, 20, 20 );
ctx.strokeRect( 40, 10.5, 20, 20 );
ctx.strokeRect( 70, 10, 20, 20 );
body { background:#eee; margin:1em; text-align:center }
canvas { background:#fff; border:1px solid #ccc; width:400px; height:160px }
<canvas width="100" height="40"></canvas>
<p>Showing that re-drawing the same antialiased lines does not obliterate old antialiased lines.</p>
A canvas has 2 sizes, the dimension of the pixels in the canvas (it's backingstore or drawingBuffer) and the display size. The number of pixels is set using the the canvas attributes. In HTML
<canvas width="400" height="300"></canvas>
Or in JavaScript
someCanvasElement.width = 400;
someCanvasElement.height = 300;
Separate from that are the canvas's CSS style width and height
In CSS
canvas { /* or some other selector */
width: 500px;
height: 400px;
}
Or in JavaScript
canvas.style.width = "500px";
canvas.style.height = "400px";
The arguably best way to make a canvas 1x1 pixels is to ALWAYS USE CSS to choose the size then write a tiny bit of JavaScript to make the number of pixels match that size.
function resizeCanvasToDisplaySize(canvas) {
// look up the size the canvas is being displayed
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// If it's resolution does not match change it
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
return true;
}
return false;
}
Why is this the best way? Because it works in most cases without having to change any code.
Here's a full window canvas:
const ctx = document.querySelector("#c").getContext("2d");
function render(time) {
time *= 0.001;
resizeCanvasToDisplaySize(ctx.canvas);
ctx.fillStyle = "#DDE";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
const spacing = 64;
const size = 48;
const across = ctx.canvas.width / spacing + 1;
const down = ctx.canvas.height / spacing + 1;
const s = Math.sin(time);
const c = Math.cos(time);
for (let y = 0; y < down; ++y) {
for (let x = 0; x < across; ++x) {
ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
ctx.strokeRect(-size / 2, -size / 2, size, size);
}
}
ctx.restore();
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resizeCanvasToDisplaySize(canvas) {
// look up the size the canvas is being displayed
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// If it's resolution does not match change it
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
return true;
}
return false;
}
body { margin: 0; }
canvas { display: block; width: 100vw; height: 100vh; }
<canvas id="c"></canvas>
And Here's a canvas as a float in a paragraph
const ctx = document.querySelector("#c").getContext("2d");
function render(time) {
time *= 0.001;
resizeCanvasToDisplaySize(ctx.canvas);
ctx.fillStyle = "#DDE";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
const spacing = 64;
const size = 48;
const across = ctx.canvas.width / spacing + 1;
const down = ctx.canvas.height / spacing + 1;
const s = Math.sin(time);
const c = Math.cos(time);
for (let y = 0; y <= down; ++y) {
for (let x = 0; x <= across; ++x) {
ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
ctx.strokeRect(-size / 2, -size / 2, size, size);
}
}
ctx.restore();
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resizeCanvasToDisplaySize(canvas) {
// look up the size the canvas is being displayed
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// If it's resolution does not match change it
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
return true;
}
return false;
}
span {
width: 250px;
height: 100px;
float: left;
padding: 1em 1em 1em 0;
display: inline-block;
}
canvas {
width: 100%;
height: 100%;
}
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent cursus venenatis metus. Mauris ac nibh at odio scelerisque scelerisque. Donec ut enim <span class="diagram"><canvas id="c"></canvas></span>
vel urna gravida imperdiet id ac odio. Aenean congue hendrerit eros id facilisis. In vitae leo ullamcorper, aliquet leo a, vehicula magna. Proin sollicitudin vestibulum aliquet. Sed et varius justo.
<br/><br/>
Quisque tempor metus in porttitor placerat. Nulla vehicula sem nec ipsum commodo, at tincidunt orci porttitor. Duis porttitor egestas dui eu viverra. Sed et ipsum eget odio pharetra semper. Integer tempor orci quam, eget aliquet velit consectetur sit amet. Maecenas maximus placerat arcu in varius. Morbi semper, quam a ullamcorper interdum, augue nisl sagittis urna, sed pharetra lectus ex nec elit. Nullam viverra lacinia tellus, bibendum maximus nisl dictum id. Phasellus mauris quam, rutrum ut congue non, hendrerit sollicitudin urna.
</p>
Here's a canvas in a sizable control panel
const ctx = document.querySelector("#c").getContext("2d");
function render(time) {
time *= 0.001;
resizeCanvasToDisplaySize(ctx.canvas);
ctx.fillStyle = "#DDE";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
const spacing = 64;
const size = 48;
const across = ctx.canvas.width / spacing + 1;
const down = ctx.canvas.height / spacing + 1;
const s = Math.sin(time);
const c = Math.cos(time);
for (let y = 0; y < down; ++y) {
for (let x = 0; x < across; ++x) {
ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
ctx.strokeRect(-size / 2, -size / 2, size, size);
}
}
ctx.restore();
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resizeCanvasToDisplaySize(canvas) {
// look up the size the canvas is being displayed
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// If it's resolution does not match change it
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
return true;
}
return false;
}
// ----- the code above related to the canvas does not change ----
// ---- the code below is related to the slider ----
const $ = document.querySelector.bind(document);
const left = $(".left");
const slider = $(".slider");
let dragging;
let lastX;
let startWidth;
slider.addEventListener('mousedown', e => {
lastX = e.pageX;
dragging = true;
});
window.addEventListener('mouseup', e => {
dragging = false;
});
window.addEventListener('mousemove', e => {
if (dragging) {
const deltaX = e.pageX - lastX;
left.style.width = left.clientWidth + deltaX + "px";
lastX = e.pageX;
}
});
body {
margin: 0;
}
.frame {
display: flex;
align-items: space-between;
height: 100vh;
}
.left {
width: 70%;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
canvas {
width: 100%;
height: 100%;
}
pre {
padding: 1em;
}
.slider {
width: 10px;
background: #000;
}
.right {
flex 1 1 auto;
}
<div class="frame">
<div class="left">
<canvas id="c"></canvas>
</div>
<div class="slider">
</div>
<div class="right">
<pre>
* controls
* go
* here
<- drag this
</pre>
</div>
</div>
here's a canvas as a background
const ctx = document.querySelector("#c").getContext("2d");
function render(time) {
time *= 0.001;
resizeCanvasToDisplaySize(ctx.canvas);
ctx.fillStyle = "#DDE";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
const spacing = 64;
const size = 48;
const across = ctx.canvas.width / spacing + 1;
const down = ctx.canvas.height / spacing + 1;
const s = Math.sin(time);
const c = Math.cos(time);
for (let y = 0; y < down; ++y) {
for (let x = 0; x < across; ++x) {
ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
ctx.strokeRect(-size / 2, -size / 2, size, size);
}
}
ctx.restore();
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resizeCanvasToDisplaySize(canvas) {
// look up the size the canvas is being displayed
const width = canvas.clientWidth;
const height = canvas.clientHeight;
// If it's resolution does not match change it
if (canvas.width !== width || canvas.height !== height) {
canvas.width = width;
canvas.height = height;
return true;
}
return false;
}
body { margin: 0; }
canvas {
display: block;
width: 100vw;
height: 100vh;
position: fixed;
}
#content {
position: absolute;
margin: 0 1em;
font-size: xx-large;
font-family: sans-serif;
font-weight: bold;
text-shadow: 2px 2px 0 #FFF,
-2px -2px 0 #FFF,
-2px 2px 0 #FFF,
2px -2px 0 #FFF;
}
<canvas id="c"></canvas>
<div id="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent cursus venenatis metus. Mauris ac nibh at odio scelerisque scelerisque. Donec ut enim vel urna gravida imperdiet id ac odio. Aenean congue hendrerit eros id facilisis. In vitae leo ullamcorper, aliquet leo a, vehicula magna. Proin sollicitudin vestibulum aliquet. Sed et varius justo.
</p>
<p>
Quisque tempor metus in porttitor placerat. Nulla vehicula sem nec ipsum commodo, at tincidunt orci porttitor. Duis porttitor egestas dui eu viverra. Sed et ipsum eget odio pharetra semper. Integer tempor orci quam, eget aliquet velit consectetur sit amet. Maecenas maximus placerat arcu in varius. Morbi semper, quam a ullamcorper interdum, augue nisl sagittis urna, sed pharetra lectus ex nec elit. Nullam viverra lacinia tellus, bibendum maximus nisl dictum id. Phasellus mauris quam, rutrum ut congue non, hendrerit sollicitudin urna.
</p>
</div>
Because I didn't set the attributes the only thing that changed in each sample is the CSS (as far as the canvas is concerned)
Notes:
Don't put borders or padding on a canvas element. Computing the size to subtract from the number of dimensions of the element is troublesome
Thank you very much! Finally I solved the blurred pixels problem with this code:
<canvas id="graph" width=326 height=240 style='width:326px;height:240px'></canvas>
With the addition of the 'half-pixel' does the trick to unblur lines.