HTML5 Canvas is not responsive - html

I have a main div, inside it are two div's each having a canvass. My problem is the canvass is not responsive, it overlaps when I resize the browser. please see below image.
Here is my HTML code:
<div id="mainContainer">
<div id="leftcolumn">
<h2>
Canvass Graph1
</h2>
<canvas id="Canvass_One"></canvas>
</div>
<div id="rightcolumn">
<h2>Canvass Graph2</h2>
<canvas id="Canvass_Two"></canvas>
</div>
</div>
CSS Code:
#mainContainer
{
width:100%;
height: 100%;
}
#leftcolumn
{
float:left;
display:inline-block;
width: -moz-calc(100% - 50%);
width: -webkit-calc(100% - 50%);
width: calc(100% - 50%);
height: 100%;
background: blue;
}
#rightcolumn {
float:left;
display:inline-block;
width: -moz-calc(100% - 50%);
width: -webkit-calc(100% - 50%);
width: calc(100% - 50%);
height: 100%;
background-color : red;
}
JS to set height and width of Canvass
var ctx2 = $("#Canvass_One").get(0).getContext('2d');
ctx2.canvas.height = 300; // setting height of canvas
ctx2.canvas.width = 560; // setting width of canvas
var ctx1 = $("#Canvass_Two").get(0).getContext('2d');
ctx1.canvas.height = 300; // setting height of canvas
ctx1.canvas.width = 560; // setting width of canvas
Canvas:
Again, my problem is when I minimized/resize the browser window , the canvass overlaps. thank you for any help. My case is that I'm not using image within my div, it's just a pure canvass with chart js framework to create a graph.
Sample data:
var barData = {
labels: ['CityA', 'CityB', 'CityC', 'CityD', 'CityF', 'CityG'],
datasets: [
{
label: '2010 customers #',
fillColor: '#382765',
data: [2500, 1902, 1041, 610, 1245, 952]
},
{
label: '2014 customers #',
fillColor: '#7BC225',
data: [3104, 1689, 1318, 589, 1199, 1436]
}
]
};

The trick is to set the style width/height in combination with the attribute width/height, as the style controls display and attribute controls image.
#Canvass_One, #Canvass_Two
{
width: 100%;
height: 100%;
}
Note: Chart.js appears to have its own setting do deal with responsiveness like this, Chart.defaults.global.responsive = true;, so one might need to combine the two.
Here is a sample to show how it works.
Chart.defaults.global.responsive = true;
var barData = {
labels: ['CityA', 'CityB', 'CityC', 'CityD', 'CityF', 'CityG'],
datasets: [
{
label: '2010 customers #',
fillColor: '#382765',
data: [2500, 1902, 1041, 610, 1245, 952]
},
{
label: '2014 customers #',
fillColor: '#7BC225',
data: [3104, 1689, 1318, 589, 1199, 1436]
}
]
};
var ctx2 = $("#Canvass_One").get(0).getContext('2d');
ctx2.canvas.height = 300; // setting height of canvas
ctx2.canvas.width = 560; // setting width of canvas
//ctx2.fillStyle = "#FF0000";
//ctx2.fillRect(10,0,450,75);
var clientsChart = new Chart(ctx2).Bar(barData);
var ctx1 = $("#Canvass_Two").get(0).getContext('2d');
ctx1.canvas.height = 300; // setting height of canvas
ctx1.canvas.width = 560; // setting width of canvas
ctx1.fillStyle = "#0000FF";
ctx1.fillRect(10,0,450,75);
#mainContainer
{
width:100%;
height: 100%;
}
#leftcolumn
{
float:left;
display:inline-block;
width: 50%;
height: 100%;
background: blue;
}
#rightcolumn
{
float:left;
display:inline-block;
width: 50%;
height: 100%;
background-color : red;
}
#Canvass_One, #Canvass_Two
{
width: 100%;
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<div id="mainContainer">
<div id="leftcolumn">
<h2>Canvass Graph1</h2>
<canvas id="Canvass_One"></canvas>
</div>
<div id="rightcolumn">
<h2>Canvass Graph2</h2>
<canvas id="Canvass_Two"></canvas>
</div>
</div>

Related

Display a Search bar on header on scroll HTML/CSS

I have a search bar which would like to display onto the header on scroll, a great example is like the one on this site: https://www.indiamart.com/
Approach 1 - A simple way to do this would be to detect a scroll & add and remove a class that contains display: none;
You can have an event listener -
window.addEventListener('scroll', function() {
if( window.scrollY !== 0) {
document.getElementById('searchBar').classList.add('scrolled');
} else {
document.getElementById('searchBar').classList.remove('scrolled');
}
});
With the CSS -
.noScroll
{
background: yellow;
position:fixed;
height: 50px; /*Whatever you want*/
width: 100%; /*Whatever you want*/
top:0;
left:0;
display:none;
}
/*Use this class when you want your content to be shown after some scroll*/
.scrolled
{
display: block !important;
}
.parent {
/* something to ensure that the parent container is scrollable */
height: 200vh;
}
And the html would be -
<div class="parent">
<div class ='noScroll' id='searchBar'>Content you want to show on scroll</div>
</div>
Here's a JSFiddle of the same - https://jsfiddle.net/kecnrh3g/
Approach 2 -
Another simple approach would be
<script>
let prevScrollpos = window.pageYOffset;
window.onscroll = function() {
let currentScrollPos = window.pageYOffset;
if (prevScrollpos > currentScrollPos) {
document.getElementById('searchBar').style.top = '-50px';
} else {
document.getElementById('searchBar').style.top = '0';
}
prevScrollpos = currentScrollPos;
}
</script>
with the html -
<div class="parent">
<div id ='searchBar'>Content you want to show on scroll</div>
</div>
and css
#searchBar {
background: yellow;
position: fixed;
top: 0;
left: 0;
height: 50px;
width: 100%;
display: block;
transition: top 0.3s;
}
.parent {
height: 200vh;
}
Here's a JSFiddle of the same - https://jsfiddle.net/0tkedcns/1/
From the same example, the idea is only to show/hide once user scroll the page using inline css display property, you can do the same or at least provide a code sample so we can help you!
HTML
<div class="search-bar">
<div class="sticky-search">
Sticky Search: <input type="text" value="search" />
</div>
</div>
CSS
.sticky-search {
display:none;
position:fixed;
top:0px;
left:0px;
right:0px;
background:blue;
padding:10px;
}
JS
var searchHeight = $(".search-bar").outerHeight();
var offset = $(".search-bar").offset().top;
var totalHeight = searchHeight + offset;
console.log(totalHeight);
$(window).scroll(function(){
if($(document).scrollTop() >= totalHeight) {
$('.sticky-search').show();
} else {
$('.sticky-search').hide();
}
});

How to scale a canvas from within a list item?

I created a 3D model with Zdog which resizes based on the size of the screen. This works as expected:
const TAU = Zdog.TAU;
let hat = new Zdog.Illustration({
element: '.zdog-canvas', // set canvas with selector
dragRotate: true,
rotate: {x: TAU/4, z: TAU/-6},
translate: {y: 20},
zoom: 4,
onResize: function( width ){
this.zoom = width / 300;
}
});
var dome = new Zdog.Hemisphere({
addTo: hat,
diameter: 80,
stroke: 20,
color: 'blue',
fill: true,
});
var brim = new Zdog.Ellipse({
addTo: dome,
width: 95,
height: 73,
quarters: 2,
stroke: 20,
translate: {y: 34},
rotate: {z: TAU/4},
fill: true,
color: 'blue'
});
function animate() {
hat.rotate.z += 0.03;
hat.updateRenderGraph();
// animate next frame
requestAnimationFrame( animate );
}
animate();
body{
margin: 0;
}
.myDiv{
height: 100%;
min-height: 100%;
margin: 0;
}
.zdog-canvas {
display: block;
position: absolute;
height: 100%;
background: #FDB;
cursor: move;
}
<script src="https://unpkg.com/zdog#1/dist/zdog.dist.min.js"></script>
<html>
<body>
<div>
<div class='myDiv'>
<canvas class="zdog-canvas" width="800" height="500"/>
</div>
</div>
</body>
</html>
However, if I place this 3d model inside of a list item, then the 3d model overflows past the bottom of the screen instead of scaling for the height of the list item. My goal is ultimately to have a list item which contains the 3d model on the left, and some text describing it on the right. How can I fix this, so that when the model is placed inside of a list item tag, it scales relative to the height of the list item?
const TAU = Zdog.TAU;
let hat = new Zdog.Illustration({
element: '.zdog-canvas', // set canvas with selector
dragRotate: true,
rotate: {x: TAU/4, z: TAU/-6},
translate: {y: 20},
zoom: 4,
onResize: function( width ){
this.zoom = width / 300;
}
});
var dome = new Zdog.Hemisphere({
addTo: hat,
diameter: 80,
stroke: 20,
color: 'blue',
fill: true,
});
var brim = new Zdog.Ellipse({
addTo: dome,
width: 95,
height: 73,
quarters: 2,
stroke: 20,
translate: {y: 34},
rotate: {z: TAU/4},
fill: true,
color: 'blue'
});
function animate() {
hat.rotate.z += 0.03;
hat.updateRenderGraph();
// animate next frame
requestAnimationFrame( animate );
}
animate();
body{
margin: 0;
}
.myIcon{
height: 100%;
min-height: 100%;
margin: 0;
}
.zdog-canvas {
display: block;
position: absolute;
height: 100%;
background: #FDB;
cursor: move;
}
li{
width: 100%;
height: 20vh;
background: red;
color: black;
}
<script src="https://unpkg.com/zdog#1/dist/zdog.dist.min.js"></script>
<html>
<body>
<div>
<ul>
<li>
<div class='flexbox-container'>
<div class='myIcon'>
<canvas class="zdog-canvas" width="800" height="500" />
</div>
<h1>some text</h1>
</div>
<div class='flexbox-container'>
<div class='myIcon'>
<canvas class="zdog-canvas" width="800" height="500" />
</div>
<h1>some text</h1>
</div>
</li>
</ul>
</div>
</body>
</html>
Solution:
const TAU = Zdog.TAU;
let hat = new Zdog.Illustration({
element: '.zdog-canvas', // set canvas with selector
dragRotate: true,
rotate: {x: TAU/4, z: TAU/-6},
translate: {y: 20},
zoom: 4,
onResize: function( width ){
//console.log('adjusted width ')
this.zoom = width / 300;
}
});
var dome = new Zdog.Hemisphere({
addTo: hat,
diameter: 80,
stroke: 20,
color: 'blue',
fill: true,
});
var brim = new Zdog.Ellipse({
addTo: dome,
//diameter: 80,
width: 95,
height: 73,
quarters: 2,
stroke: 20,
translate: {y: 34},
rotate: {z: TAU/4},
fill: true,
color: 'blue'
});
//illo.updateRenderGraph();
function animate() {
// rotate illo each frame
hat.rotate.z += 0.03;
hat.updateRenderGraph();
// animate next frame
requestAnimationFrame( animate );
}
animate();
body{
margin: 0;
}
.flexbox-container{
display: flex;
flex-direction: row;
}
.myIcon{
flex: 1;
height: 100%;
min-height: 100%;
margin: 0;
}
.text-div{
flex: 1;
}
.zdog-canvas {
display: block;
position: absolute;
height: 100%;
max-height: 20vh;
background: #FDB;
cursor: move;
}
.list-item{
width: 100%;
height: 20vh;
background: red;
color: black;
margin: 1vw 0;
}
<script src="https://unpkg.com/zdog#1/dist/zdog.dist.min.js"></script>
<html>
<body>
<div>
<ul>
<li class="list-item">
<div class='flexbox-container'>
<div class='myIcon'>
<canvas class="zdog-canvas" width="800" height="500" />
</div>
<div class="text-div"> stuff</div>
</div>
</li>
<li class="list-item">
<div class='flexbox-container'>
<div class='myIcon'>
<canvas class="zdog-canvas" width="800" height="500" />
</div>
<div class="text-div"> stuff</div>
</div>
</li>
</ul>
</div>
</body>
</html>

Google Chart height cannot be increased

I have this Google Chart (Line Graph) code:
<html>
<head>
<style>
.chart {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
min-height: 500px;
}
#chart {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
min-height: 500px;
}
</style>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['line']});
google.charts.setOnLoadCallback(drawChart);
window.addEventListener('resize', function (event) {
drawChart();
});
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'Day');
data.addColumn('number', 'Guardians of the Galaxy');
data.addColumn('number', 'The Avengers');
data.addColumn('number', 'Transformers: Age of Extinction');
data.addRows([
[1, 37.8, 80.8, 41.8],
[2, 30.9, 69.5, 32.4],
[3, 25.4, 57, 25.7],
[4, 11.7, 18.8, 10.5],
[5, 11.9, 17.6, 10.4],
[6, 8.8, 13.6, 7.7],
[7, 7.6, 12.3, 9.6],
[8, 12.3, 29.2, 10.6],
[9, 16.9, 42.9, 14.8],
[10, 12.8, 30.9, 11.6],
[11, 5.3, 7.9, 4.7],
[12, 6.6, 8.4, 5.2],
[13, 4.8, 6.3, 3.6],
[14, 4.2, 6.2, 3.4]
]);
var options = {
chart: {
title: 'Box Office Earnings in First Two Weeks of Opening',
subtitle: 'in millions of dollars (USD)'
},
// width: 1800,
// height: 1000,
axes: {
x: {
0: {side: 'top'}
}
}
};
var chart = new google.charts.Line(document.getElementById('line_top_x'));
chart.draw(data, google.charts.Line.convertOptions(options));
}
</script>
</head>
<body>
<div id="line_top_x"></div>
</body>
</html>
you can write that to a file and just open it with a browser - it renders fine, but I cannot get the height of the graph to increase no matter what I add to the css (the style tag).
Anyone know how to get the height to be 100% of the page?
As you can see from the screenshot, the graph is squashed where the height is only about 100px.
I added the following CSS:
body {
width:80%;
height:80%;
margin:10% auto;
background:#e6e6e6;
}
#chart_wrap {
border:1px solid gray;
position: relative;
padding-bottom: 100%;
height: 0;
overflow:hidden;
}
#chart {
position: absolute;
top: 0;
left: 0;
width:100%;
height:100%;
}
and I still cannot get the height to increase:
I think I need to use this to alter the width/height
var options = {
chart: {
title: 'Node.js memory usage (RSS, Heap Used, Heap Total)',
subtitle: '(In megabytes.)'
},
// width: 1800,
// height: 1000,
axes: {
x: {
0: {side: 'top'}
}
}
};
var chart = new google.charts.Line(document.getElementById('line_top_x'));
chart.draw(data, google.charts.Line.convertOptions(options));
but I don't know what to use for height/width to make it 100% of the window/container.
add this css
#line_top_x {
height: 100vh;
}

Can I do image orientation detection with html or css?

If I have an image on html page, can I use html or css do the following?
When width of the image is greater than height, set height to a fixed value and auto stretch width; when height is greater than width, set width and auto stretch height?
Thanks a lot!
No, this is not possible - conditional statements cannot be handled with HTML or CSS, but you have to do it with JS.
An example would be calculating (and perhaps storing for future use) the aspect ratio of an image to determine whether is it in landscape or portrait mode:
$(document).ready(function() {
$("img").each(function() {
// Calculate aspect ratio and store it in HTML data- attribute
var aspectRatio = $(this).width()/$(this).height();
$(this).data("aspect-ratio", aspectRatio);
// Conditional statement
if(aspectRatio > 1) {
// Image is landscape
$(this).css({
width: "100%",
height: "auto"
});
} else if (aspectRatio < 1) {
// Image is portrait
$(this).css({
maxWidth: "100%"
});
} else {
// Image is square
$(this).css({
maxWidth: "100%",
height: "auto"
});
}
});
});
See fiddle here - http://jsfiddle.net/teddyrised/PkgJG/
2019 update: As ES6 is becoming the defacto standard, the above jQuery code can be easily refactored into vanilla JS:
const images = document.querySelectorAll('img');
Array.from(images).forEach(image => {
image.addEventListener('load', () => fitImage(image));
if (image.complete && image.naturalWidth !== 0)
fitImage(image);
});
function fitImage(image) {
const aspectRatio = image.naturalWidth / image.naturalHeight;
// If image is landscape
if (aspectRatio > 1) {
image.style.width = '100%';
image.style.height = 'auto';
}
// If image is portrait
else if (aspectRatio < 1) {
image.style.width = 'auto';
image.style.maxHeight = '100%';
}
// Otherwise, image is square
else {
image.style.maxWidth = '100%';
image.style.height = 'auto';
}
}
div.wrapper {
background-color: #999;
border: 1px solid #333;
float: left;
margin: 10px;
width: 200px;
height: 250px;
}
<div class="wrapper">
<img src="http://placehold.it/500x350" />
</div>
<div class="wrapper">
<img src="http://placehold.it/350x500" />
</div>
<div class="wrapper">
<img src="http://placehold.it/500x500" />
</div>
However, if all you want is to ensure the image fits within an arbitrary sized container, using simple CSS will work:
div.wrapper {
background-color: #999;
border: 1px solid #333;
float: left;
margin: 10px;
width: 400px;
height: 400px;
}
div.wrapper img {
width: auto
height: auto;
max-width: 100%;
max-height: 100%;
}
<div class="wrapper">
<img src="http://placehold.it/500x350" />
</div>
<div class="wrapper">
<img src="http://placehold.it/350x500" />
</div>
<div class="wrapper">
<img src="http://placehold.it/500x500" />
</div>

Make a draggable HTML5 canvas curve area

If I have a canvas in which an image is drawn. The image has four points in the curve. I need to make this curve area draggable.
but without use of kinetic Js
Image attached.
HTML
<div id='curveAreaDrag' class="ui-widget-content" >
<div id="point1" class="ui-widget-content"></div>
<div id="point2" class="ui-widget-content"></div>
<div id="point3" class="ui-widget-content"></div>
<div id="point4" class="ui-widget-content"></div>
</div>
<canvas id="myCanvas" width="400px" height="400px"
style="border:1px solid #d3d3d3;top:0;left:0"></canvas>
jQuery
$("#curveAreaDrag").draggable({drag:function(){save();}});
Updated:
I have four points of bezier curve. i am also scaling each point then the light black area also scaling.
i need to drag the light black area. it is not an image. it is selected area by bezier curve.
[ Edited: To fit OP’s additional information ]
This code uses 2 Cubic Bezier Curves and 6 control handles to let you select the eyeball in your image.
The Red handles control the curve on the top part of the eye. The Blue handles control the curve on the bottom part of the eye. The White handles let you anchor on the corners of the eye. The Orange shows the resulting path (=2 curves).
Below is a picture of the app and here is a Fiddle of it in action: http://jsfiddle.net/m1erickson/98G9F/
Here is the code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.1/jquery-ui.js"></script>
<style>
body { font-family: arial; }
.anchor { background: #fff; position: absolute; display: block; height: 10px; width: 10px; border: 1px solid #333; border-radius:5px;}
.control { background: #fff; position: absolute; display: block; height: 20px; width: 20px; border: 1px solid #333; border-radius:10px;}
.p1, .p2 { background: red; z-index: 50; }
.p3, .p4 { background: blue; }
.pStart { background:white;}
.pEnd {background:white;}
.pStart { left: 54px; top: 166px; }
.pEnd { left: 346px; top: 189px; }
.p1 { left: 150px; top: 39px; }
.p2 { left: 276px; top: 97px; }
.p3 { left: 219px; top: 227px; }
.p4 { left: 147px; top: 224px; }
canvas { border: 1px solid #333;}
#start,#end2{color:green;}
#end1{color:purple;}
#c1,#c3{color:red;}
#c2,#c4{color:blue;}
</style>
</head>
<body>
<canvas height="400" width="400" id="canvas"></canvas>
<p>context.moveTo(
<span id="start"></span>);
</p>
<p>context.bezierCurveTo(
<span id="c1"></span>,
<span id="c2"></span>,
<span id="end1"></span>);
</p>
<p>context.bezierCurveTo(
<span id="c3"></span>,
<span id="c4"></span>,
<span id="end2"></span>);
</p>
<script>
var $p1,$p2,$codeMove,$codeBez1,$codeBez2;
$(function() {
var canvas=document.getElementById("canvas");
var ctx = canvas.getContext("2d");
$pStart=$(".pStart");
$pEnd=$(".pEnd");
$p1 = $(".p1");
$p2 = $(".p2");
$p3 = $(".p3");
$p4 = $(".p4");
$codeMove=$("code-move");
$codeBez1=$("code-bez1");
$codeBez2=$("code-bez2");
$(".pStart, .pEnd, .p1, .p2, .p3, .p4").draggable({
containment: 'parent',
drag: function(event, ui) { renderWrap(ctx); },
stop: function(){ renderWrap(ctx); }
});
var eyeImage=new Image();
eyeImage.onload=function(){
canvas.width=eyeImage.width*1.5;
canvas.height=eyeImage.height*1.5;
renderWrap(ctx);
}
eyeImage.src="http://i.stack.imgur.com/SbcL4.png";
function renderWrap(ctx) {
var pStart=$pStart.position();
var pEnd=$pEnd.position();
var p1 = $p1.position();
var p2 = $p2.position();
var p3 = $p3.position();
var p4 = $p4.position();
render({x:pStart.left, y:pStart.top}, {x:pEnd.left, y:pEnd.top}, {x:p1.left, y:p1.top}, {x:p2.left, y:p2.top}, {x:p3.left, y:p3.top}, {x:p4.left, y:p4.top} );
};
function render(start, end, p1, p2, p3, p4) {
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(eyeImage,0,0,eyeImage.width,eyeImage.height,0,0,eyeImage.width*1.5,eyeImage.height*1.5);
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = "orange";
// start-->end
ctx.moveTo(start.x,start.y);
ctx.bezierCurveTo(p1.x,p1.y,p2.x,p2.y,end.x,end.y);
ctx.stroke();
// end-->start
ctx.bezierCurveTo(p3.x,p3.y,p4.x,p4.y,start.x,start.y);
ctx.stroke();
ctx.closePath();
// connectors
ctx.beginPath();
ctx.strokeStyle = "#999";
ctx.lineWidth = 1;
connector(start,p1);
connector(end,p2);
connector(end,p3);
connector(start,p4);
ctx.closePath();
// display code
$("#start").html(start.x+","+start.y);
$("#c1").html(p1.x+","+p1.y);
$("#c2").html(p2.x+","+p2.y);
$("#end1").html(end.x+","+end.y);
$("#c3").html(p3.x+","+p3.y);
$("#c4").html(p4.x+","+p4.y);
$("#end2").html(start.x+","+start.y);
}
function connector(pt1,pt2){
ctx.moveTo(pt1.x,pt1.y);
ctx.lineTo(pt2.x,pt2.y);
ctx.stroke();
}
});
</script>
</body>
</html>