d3.js inline-block elements are failing in Firefox and IE - css

I've trying to combine inline a small d3.js animation with a separate image, but can't get it to work cross-browser. My code works OK in Chrome and Safari but not Firefox, or properly in Internet Explorer. In FF they're not inline. For IE I followed this tip - they do render inline, but with a big gap.
Assistance much appreciated. Here's a jsfiddle of the model. As it's a css problem I think only the top 2 javascript chains might be relevant - the rest is animation.
<!DOCTYPE html>
<html>
<head>
<title>In-line problem</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style type="text/css">
.img {-webkit-backface-visibility: hidden;}
#container .logoElement{
display: inline-block;
*display: inline;
zoom: 1;
width: 400;
}
</style>
</head>
<body>
<span id="container">
<div id="d3div" class="logoElement"></div>
<div id="imagediv" class="logoElement"></div>
</span>
<script>
// right-side (static) image element
d3.select("#imagediv").append("img")
.attr("src", "https://cdn.tutsplus.com/mobile/uploads/legacy/Free-App-Marketing-Tips/city-landscape.png")
.style("max-width", "200px")
.attr("class", "logoElement");
// left-side (dynamic) d3 element
var g = d3.select("#d3div").append("svg")
.attr("class", "logoElement")
.style("height", 110)
.style("width", 180)
.append("g")
.attr("transform", "scale(1.1)");
// I THINK BELOW CAN BE IGNORED
var start = Date.now(),
speed = .02;
// initialise dynamic animation elements
var big = g.append("image")
.attr("xlink:href", "http://www.cs.cmu.edu/~junggon/tools/gear.png")
.attr("class", "img")
.attr("width", 100).attr("height", 100)
.attr("x", -50).attr("y", -50);
var small = g.append("image")
.attr("xlink:href", "http://www.cs.cmu.edu/~junggon/tools/gear.png")
.attr("class", "img")
.attr("width", 50).attr("height", 50)
.attr("x", -25).attr("y", -25);
// animate
d3.timer(function() {
var angle = (Date.now() - start) * speed,
transform = function(d) { return "translate(50,50)," + "rotate(" + angle/2 + ")"; };
big.selectAll("frame").attr("transform", transform);
big.attr("transform", transform);
});
d3.timer(function() {
var angle = (Date.now() - start) * speed,
transform = function(d) { return "translate(124,50)," + "rotate(" + -angle + ")"; };
small.selectAll("frame").attr("transform", transform);
small.attr("transform", transform);
});
</script>
</body>
</html>

you forgot a unit to your width declaration for your .logoElement.
Also set a white-space: nowrap; to the container, just to be sure to always have the elements aligned side by side with no line-breaks
Example fiddle: http://jsfiddle.net/xm3fLyxz/6/

Demo
#container .logoElement{
display: inline-block;
*display: inline;
zoom: 1;
width: 200px; /* You forgot to add 'px', to show it in one line I reduced the width */
}

Related

CSS image over JS animated image

I created following simple website. I have Starfield and galaxy pictures. Starfield is animated by JS code. Stars are moving. But when I place Galaxy over starfield with CSS code stars stop moving.
Below I placed JS code and HTML code without placing galaxy over starfield. How can I place one over another with stars moving?
Regards
Piotr
<head>
<meta charset ="utf-8">
<title> Galaktyka</title>
<script src ="Code17.js"></script>
<style>
#galaxy{
display: block;
margin-left: 0;
margin-top: 0;
}
#star{
position: relative;
}
</style>
</head>
<body>
<script>
window.onscroll = function () {
window.scrollTo(0,0);
}
</script>
<style type="text/css">
body {
overflow: hidden;
}
</style>
<img id="galaxy" src="Galaktyka.jpg" style="width: 70%">
<img id="star" src="starfield.jpg">
</body>
And below JS
window.onload = function(){
let image = document.getElementById("star");
imageLeft = -175;
setInterval(move, 100, image);
}
var motion = true;
function move() {
if(motion) {
let image = document.getElementById("star");
imageLeft = imageLeft + 1;
image.style.left = imageLeft + "px";
if (imageLeft == 0) {
motion = false;
} else {
let image = document.getElementById("star");
imageLeft = imageLeft - 1;
image.style.left = imageLeft + "px";
}
if (imageLeft == -175){
motion = true;
}
}
}

adding animation to flex-wrap

when it comes to wrap point how can we add animation?
maybe this can help:
we have a header and inside of that header we have container with flex attr and the direction is column when we resize our browser from bottom to top or when we changing height of browser those items suddenly reshape , I just want to add animation to this event.thx
<header>
<div class="container">
<div class="item1 item"></div>
<div class="item2 item"></div>
<div class="item3 item"></div></div></header>
header {
width: 200vw;
max-height: 100vh ;
}
.container{
display: flex;
max-height:100vh;
flex-direction: column;
flex-wrap: wrap;
align-content:flex-start;
}
.item1 {
background-color: red;
height: 200px;
flex: 1 0 150px;
}
.item2 {
background-color: blue;
height: 200px;
flex: 1 0 150px;
}
.item3 {
background-color: orange;
height: 200px;
flex: 1 0 150px;
}
I had a similar need and created a simple utility to achieve it.
- Demo at CodePen: https://codepen.io/hideya/pen/Jamabx
- GH gist: https://gist.github.com/hideya/16ed168a42f74eb5d2162b4e743940ff
The implementation is a bit wild and pretty much assumes no change in flex items except xy coords. You may need to adjust z-index, as it switches item's 'position' to 'absolute'.
Hope this helps.
window.addEventListener('load', function(event) {
var targetClassName = 'flex-wrap-anim';
var defaultDuration = '0.3s';
var dummyList = [];
function addDummy(item, duration) {
var top = item.offsetTop;
var left = item.offsetLeft;
setTimeout(function() {
item.style.position = 'absolute';
item.style.top = top + 'px';
item.style.left = left + 'px';
var dummyDiv = document.createElement('div');
dummyDiv.classList.add(targetClassName + '-dummy');
var rect = item.getBoundingClientRect();
dummyDiv.style.width = rect.width + 'px';
dummyDiv.style.height = rect.height + 'px';
dummyDiv.style.visibility = 'hidden';
dummyDiv['__' + targetClassName + '_pair'] = item;
dummyDiv['__' + targetClassName + '_duration'] = duration;
item.parentNode.appendChild(dummyDiv);
dummyList.push(dummyDiv);
}, 0);
}
var conts = document.getElementsByClassName(targetClassName);
for (var i = 0, max = conts.length; i < max; i++) {
var cont = conts[i];
cont.style.positoin = 'relative';
var duration = cont.getAttribute('data-duration')
|| defaultDuration;
var items = cont.getElementsByTagName('div');
for (var i = 0, max = items.length; i < max; i++) {
addDummy(items[i], duration);
}
}
window.addEventListener('resize', function(event) {
dummyList.forEach(function(dummyDiv) {
var item = dummyDiv['__' + targetClassName + '_pair'];
var duration = dummyDiv['__' + targetClassName + '_duration'];
if (item.offsetTop != dummyDiv.offsetTop) {
item.style.transition = 'all ' + duration;
item.style.top = dummyDiv.offsetTop + 'px';
item.style.left = dummyDiv.offsetLeft + 'px';
} else {
item.style.transition = '';
item.style.left = dummyDiv.offsetLeft + 'px';
}
});
});
});
While this cannot be done with CSS alone, you can accomplish this using JQuery. When looking at a flexbox using rows, the flexbox will change height if a new row is created or removed. Knowing this, we can add a .resize() function to the page to test if a window resize has altered the height of the flexbox. If it has, you can then execute an animation. I have created an example JFiddle here.
Here is the code that makes this work:
$(document).ready(function() {
var height = $('.container').css('height');
var id;
$(window).resize(function() {
clearTimeout(id);
id = setTimeout(doneResizing, 500);
});
function doneResizing() {
var newheight = $('.container').css('height');
if (newheight != height) {
$('.item').fadeOut();
$('.item').fadeIn();
height = newheight;
}
}
});
Now with a flexbox using columns, we need to detect when a change in width occurs. This is slightly more difficult as the flexbox width will take up the maximum allotted width as it is a block style element by default. So to accomplish this, you either need to set it as an inline flexbox using display: inline-flex, or set a maximum width for the flexbox equal to the width of its contents at its largest. Once you have set one of those, you can use the same code as above, except tweaking it to detect changes in width as opposed to height.
These changes applied an animation to all elements on resize. What if you want to only apply it to the element whose row/column changes? This would take more effort but is do-able. You would need to write many if-statements in your javascript/jquery code to catch which flex-item to apply the animation to based on width/height.

zooming content inside div using transform scale property

I am trying to zoom contents of div(same behavior as browser zoom). After searching a lot I found css 3 transform scale property will full fill this requirement.
The content is zooming when I increase the scale size but I am losing the contents of the div. overflow: hidden also didn't help.
var currentZoom = 1.0;
$(document).ready(function () {
$('#btn_ZoomIn').click(
function () {
currentZoom = currentZoom+0.04;
var scaleString = "scale("+currentZoom+")";
$('#divName').css("transform", scaleString);
})
$('#btn_ZoomOut').click(
function () {
//var scaleString = "scale("+currentZoom -= .1+")";
currentZoom = currentZoom-0.04;
var scaleString = "scale("+currentZoom+")";
$('#divName').css("transform", scaleString);
})
});
Js fiddle link: http://jsfiddle.net/chaitut715/k4WsB/
Add a container around #divName:
<div class="wrapper">
<div id="divName">
<img src="https://www.google.co.in/intl/en_ALL/images/srpr/logo11w.png"></img>
</div>
</div>
And set overflow: hidden; on the new container:
.wrapper {
overflow: hidden; /* 'auto' would probably be better */
width: 500px;
}
Working demo

CSS Sprite Animation problem on Mobile Browser (residual image)

Try the following link in any web browser on your desktop and then try it on any mobile browser (tried it on Android, iPhone & iPad - all produce same problem) and can someone tell me why the first 'frame' (well original sprite position) is always displayed behind the animation?
http://24hours-in.lincoln.ac.uk/projects/mus/animate2.html
Thanks!
Solved it! (with a fudge)
var character = null;
var xOffset = 0;
function animate() {
if(xOffset < 360){
xOffset += 30;
} else {
xOffset = 0;
}
character = document.getElementById("character");
character.style.backgroundImage = "url('char2.png')";
character.style.backgroundPosition = xOffset + "px 0px";
setTimeout(animate,250);
}
function init() {
var character = document.createElement("div");
character.id = "character";
character.style.backgroundImage = "url('spacer.png')";
character.style.position = "absolute";
character.style.width = "30px";
character.style.height = "65px";
document.getElementById("stage").appendChild(character);
animate();
}
window.onload = init;
I figured it was using a background fallback of the original image because of the transparency. Therefore, instead of starting off with the background image, I started off by applying a 1px transparent PNG file (abut assigning the rest of the CSS ready for the char PNG) and when it comes to the animation, I then substitute the background image to the char.PNG version.
I am sure there are more elegant ways, but this does the job!
You know, to be honest, I don't know what causes the issue, but the issue is that the character background-image is static - that is to say, it's set in stone (via css).
A fix around your issue is to dynamically add the background-image using javascript. Here's your revised code.
CSS
<style type="text/css">
body {
padding: 0px;
margin: 0px;
}
#character {
position:absolute;
width:30px;
height:65px;
background-position: center center;
overflow: hidden;
}
</style>
Javascript
<script type="text/javascript">
var character = null;
var xOffset = 0;
function animate() {
if(xOffset < 360){
xOffset += 30;
} else {
xOffset = 0;
}
character.style.backgroundImage = "url('char.png')";
character.style.backgroundPosition = xOffset + 'px, 0px';
setTimeout(animate,250);
}
function init() {
character = document.getElementById("character");
animate();
}
window.onload = init;
</script>
HTML
<body>
<div id="character"></div>
</body>

Centering a canvas

How do I markup a page with an HTML5 canvas such that the canvas
Takes up 80% of the width
Has a corresponding pixel height and width which effectively define the ratio (and are proportionally maintained when the canvas is stretched to 80%)
Is centered both vertically and horizontally
You can assume that the canvas is the only thing on the page, but feel free to encapsulate it in divs if necessary.
This will center the canvas horizontally:
#canvas-container {
width: 100%;
text-align:center;
}
canvas {
display: inline;
}
HTML:
<div id="canvas-container">
<canvas>Your browser doesn't support canvas</canvas>
</div>
Looking at the current answers I feel that one easy and clean fix is missing. Just in case someone passes by and looks for the right solution.
I am quite successful with some simple CSS and javascript.
Center canvas to middle of the screen or parent element. No wrapping.
HTML:
<canvas id="canvas" width="400" height="300">No canvas support</canvas>
CSS:
#canvas {
position: absolute;
top:0;
bottom: 0;
left: 0;
right: 0;
margin:auto;
}
Javascript:
window.onload = window.onresize = function() {
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth * 0.8;
canvas.height = window.innerHeight * 0.8;
}
Works like a charm - tested: firefox, chrome
fiddle: http://jsfiddle.net/djwave28/j6cffppa/3/
easiest way
put the canvas into paragraph tags like this:
<p align="center">
<canvas id="myCanvas" style="background:#220000" width="700" height="500" align="right"></canvas>
</p>
Tested only on Firefox:
<script>
window.onload = window.onresize = function() {
var C = 0.8; // canvas width to viewport width ratio
var W_TO_H = 2/1; // canvas width to canvas height ratio
var el = document.getElementById("a");
// For IE compatibility http://www.google.com/search?q=get+viewport+size+js
var viewportWidth = window.innerWidth;
var viewportHeight = window.innerHeight;
var canvasWidth = viewportWidth * C;
var canvasHeight = canvasWidth / W_TO_H;
el.style.position = "fixed";
el.setAttribute("width", canvasWidth);
el.setAttribute("height", canvasHeight);
el.style.top = (viewportHeight - canvasHeight) / 2;
el.style.left = (viewportWidth - canvasWidth) / 2;
window.ctx = el.getContext("2d");
ctx.clearRect(0,0,canvasWidth,canvasHeight);
ctx.fillStyle = 'yellow';
ctx.moveTo(0, canvasHeight/2);
ctx.lineTo(canvasWidth/2, 0);
ctx.lineTo(canvasWidth, canvasHeight/2);
ctx.lineTo(canvasWidth/2, canvasHeight);
ctx.lineTo(0, canvasHeight/2);
ctx.fill()
}
</script>
<body>
<canvas id="a" style="background: black">
</canvas>
</body>
in order to center the canvas within the window +"px" should be added to el.style.top and el.style.left.
el.style.top = (viewportHeight - canvasHeight) / 2 +"px";
el.style.left = (viewportWidth - canvasWidth) / 2 +"px";
Resizing canvas using css is not a good idea. It should be done using Javascript. See the below function which does it
function setCanvas(){
var canvasNode = document.getElementById('xCanvas');
var pw = canvasNode.parentNode.clientWidth;
var ph = canvasNode.parentNode.clientHeight;
canvasNode.height = pw * 0.8 * (canvasNode.height/canvasNode.width);
canvasNode.width = pw * 0.8;
canvasNode.style.top = (ph-canvasNode.height)/2 + "px";
canvasNode.style.left = (pw-canvasNode.width)/2 + "px";
}
demo here : http://jsfiddle.net/9Rmwt/11/show/
.
Simple:
<body>
<div>
<div style="width: 800px; height:500px; margin: 50px auto;">
<canvas width="800" height="500" style="background:#CCC">
Your browser does not support HTML5 Canvas.
</canvas>
</div>
</div>
</body>
Given that canvas is nothing without JavaScript, use JavaScript too for sizing and positionning (you know: onresize, position:absolute, etc.)
As to the CSS suggestion:
#myCanvas {
width: 100%;
height: 100%;
}
By the standard, CSS does not size the canvas coordinate system, it scales the content. In Chrome, the CSS mentioned will scale the canvas up or down to fit the browser's layout. In the typical case where the coordinate system is smaller than the browser's dimensions in pixels, this effectively lowers the resolution of your drawing. It most likely results in non-proportional drawing as well.
Same codes from Nickolay above, but tested on IE9 and chrome (and removed the extra rendering):
window.onload = window.onresize = function() {
var canvas = document.getElementById('canvas');
var viewportWidth = window.innerWidth;
var viewportHeight = window.innerHeight;
var canvasWidth = viewportWidth * 0.8;
var canvasHeight = canvasWidth / 2;
canvas.style.position = "absolute";
canvas.setAttribute("width", canvasWidth);
canvas.setAttribute("height", canvasHeight);
canvas.style.top = (viewportHeight - canvasHeight) / 2 + "px";
canvas.style.left = (viewportWidth - canvasWidth) / 2 + "px";
}
HTML:
<body>
<canvas id="canvas" style="background: #ffffff">
Canvas is not supported.
</canvas>
</body>
The top and left offset only works when I add px.
Make a line in the center and make it transparent.
This line will be the fulcrum to center the content in the canvas
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.strokeStyle = 'transparent';
context.moveTo(width/2, 0);
context.lineTo(width/2, height);
context.stroke();
context.textAlign = 'center';
with width height being the size of the html canvas
Wrapping it with div should work. I tested it in Firefox, Chrome on Fedora 13 (demo).
#content {
width: 95%;
height: 95%;
margin: auto;
}
#myCanvas {
width: 100%;
height: 100%;
border: 1px solid black;
}
And the canvas should be enclosed in tag
<div id="content">
<canvas id="myCanvas">Your browser doesn't support canvas tag</canvas>
</div>
Let me know if it works. Cheers.

Resources