SVG keyframe not animating radius and coordinates in Firefox/Safari - svg

I've been trying to re-create the Google Ripple effect for buttons. You can see it: here
It works in Chrome, but only in chrome. And I can't seem to figur out why.
I am making the ripple like this: On click, create an svg inside the button. Which is placed at the right position using mouse coordinates. Then it is animated trough css keyframe animations, which animate the circle radius (r="*").
css:
body .custom-container .btn-custom .ripple-svg circle {
opacity: 0;
transform: traslateZ(0);
-webkit-animation: flowAnimation 1s;
-moz-animation: flowAnimation 1s;
-o-animation: flowAnimation 1s;
animation: flowAnimation 1s;
}
#-webkit-keyframes flowAnimation {
0% {
r: 5;
opacity: 0;
}
10% {
opacity: 0.3;
}
50% {
opacity: 0.2;
}
90% {
r: 300;
opacity: 0;
}
100% {
r: 5;
opacity: 0;
}
}
#-moz-keyframes flowAnimation {
0% {
r: 5;
opacity: 0;
}
10% {
opacity: 0.3;
}
50% {
opacity: 0.2;
}
90% {
r: 300;
opacity: 0;
}
100% {
r: 5;
opacity: 0;
}
}
#-o-keyframes flowAnimation {
0% {
r: 5;
opacity: 0;
}
10% {
opacity: 0.3;
}
50% {
opacity: 0.2;
}
90% {
r: 300;
opacity: 0;
}
100% {
r: 5;
opacity: 0;
}
}
#keyframes flowAnimation {
0% {
r: 5;
opacity: 0;
}
10% {
opacity: 0.3;
}
50% {
opacity: 0.2;
}
90% {
r: 300;
opacity: 0;
}
100% {
r: 5;
opacity: 0;
}
}
JS:
// Mouse coordinates in button
var MousePosX
var MousePosY
var offset = $("#flow-button").offset();
// Set coordinates on mouse move
$('#flow-button').on( "mousemove", function( event ) {
MousePosX = ( event.pageX - offset.left);
MousePosY = ( event.pageY - offset.top + 15);
});
// Ripple effect
$('#flow-button').on("click", function(){
// Append svg circle on each click
$('#flow-button').append('<svg class="ripple-svg" height="100%" width="100%"><circle r="10" fill="black" /></svg>');
// Append is following mouse coordinates
$('.ripple-svg circle').css({
cx: MousePosX,
cy: MousePosY
});
// On multiple clicks delete all but the last one
if ($('.ripple-svg').length > 2) {
$('.ripple-svg:not(:last-child)').remove();
}
});
Anyone any idea?

In SVG 1.1 radius (r) is an attribute and not a CSS property. In SVG 2 it is proposed that most attributes should become CSS properties.
SMIL can animate both attributes and CSS properties but CSS animations can only animate CSS properties.
Chrome has implemented this part of the SVG 2 specification (to see how feasible it is). No other UA has done so yet but in the future any of them might do so.

Related

Change color of hamburger menu on hover/click

Let me just say that my knowledge in coding is very minimal. I am trying to figure out how to turn the hamburger menu from the current color to white when the cursor hovers it or when you click it. I hope that makes sense! It will be three white lines on a black background, so it will be visible.
I have tried adding color: #fff; but I think there needs to be some specific line of coding to actually change the hamburger menu on hover/click. I am unaware of this code.
Please let me know if I included the right CSS for what I am asking about! I added the custom js in case it is needed!
/* Header */
.header-wrap #logo {
display: table-cell;
vertical-align: middle;
width: 100%;
font-size: 2em;
text-align: center;
}
.header-wrap #logo #wsite-title {
font-size: inherit !important;
}
.header-wrap .wsite-logo {
padding: 0 50px;
}
.header-wrap .wsite-logo a img {
max-height: 40px;
}
.header-wrap .search {
display: none;
}
.header-wrap .nav-wrap {
position: fixed;
display: table;
background: #shade;
top: 0;
left: 0;
z-index: 15;
height: 55px;
-webkit-transition: all 610ms cubic-bezier(0, 0.8, 0.55, 1);
-moz-transition: all 610ms cubic-bezier(0, 0.8, 0.55, 1);
-ms-transition: all 610ms cubic-bezier(0, 0.8, 0.55, 1);
-o-transition: all 610ms cubic-bezier(0, 0.8, 0.55, 1);
transition: all 610ms cubic-bezier(0, 0.8, 0.55, 1);
}
.header-wrap .nav-wrap ul {
padding: 0 4em;
}
.header-wrap .hamburger {
position: absolute;
top: 0;
right: 0;
display: block;
width: 30px;
height: 30px;
padding: 10px;
cursor: pointer;
}
.header-wrap .hamburger span,
.header-wrap .hamburger span:before,
.header-wrap .hamburger span:after {
position: relative;
display: block;
width: 20px;
height: 2px;
background: #color;
content: '';
}
.header-wrap .hamburger span {
top: 10px;
left: 4px;
margin: 6px 0;
}
.header-wrap .hamburger span:before {
top: -8px;
}
.header-wrap .hamburger span:after {
bottom: -6px;
}
jQuery(function($) {
// Mobile sidebars
$.fn.expandableSidebar = function(expandedClass) {
var $me = this;
$me.on('click', function() {
if(!$me.hasClass(expandedClass)) {
$me.addClass(expandedClass);
} else {
$me.removeClass(expandedClass);
}
});
}
var haberdasherController = {
init: function(opts) {
var base = this;
// Add classes to elements
base._attachEvents();
setTimeout(function(){
base._addClasses();
base._checkCartItems();
}, 1000);
},
_addClasses: function() {
var base = this;
// Add placeholder text to inputs
$('.wsite-form-sublabel').each(function(){
var sublabel = $(this).text();
$(this).prev('.wsite-form-input').attr('placeholder', sublabel);
});
// Add fullwidth class to gallery thumbs if less than 6
$('.imageGallery').each(function(){
if ($(this).children('div').length <= 6) {
$(this).children('div').addClass('fullwidth-mobile');
}
});
},
_stickyFooter: function() {
var stickyFooterMargin = $('#footer-wrap').height();
$('.wrapper').css('margin-bottom', -stickyFooterMargin);
$('#footer-wrap, .sticky-footer-push').css('height', stickyFooterMargin);
},
_checkCartItems: function() {
var base = this;
if($('#wsite-mini-cart').find('li.wsite-product-item').length > 0) {
$('#wsite-mini-cart').addClass('full');
base.cartHasItems = true;
} else {
$('#wsite-mini-cart').removeClass('full');
base.cartHasItems = false;
}
},
_attachEvents: function() {
var base = this;
$('.hamburger').on('click', function(e) {
e.preventDefault();
$('body').toggleClass('nav-open');
});
// Pad header on mobile
setTimeout(function(){
if($(window).width() < 992) {
$(".banner-wrap").css({"padding-top" : $(".header-wrap > .nav-wrap").height() + "px"});
}
}, 800);
// Copy login and search to mobile nav
var login = $("#member-login").clone(true),
search = $("#wsite-header-search-form").clone(true)
$("#navmobile .wsite-menu-default").append(login).append(search);
// Menu text alignment
if($('.search').is(':empty') || $('.search').css('display') == 'none') {
$('.menu').css('text-align', 'center');
}
// Store category dropdown
$('.wsite-com-sidebar').expandableSidebar('sidebar-expanded');
// Search filters dropdown
$('#wsite-search-sidebar').expandableSidebar('sidebar-expanded');
// Init fancybox swipe on mobile
if('ontouchstart' in window) {
$('body').on('click', 'a.w-fancybox', function() {
base._initSwipeGallery();
});
}
// Init sticky footer
if($(window).width() > 992) {
base._stickyFooter();
}
},
_initSwipeGallery: function() {
var base = this;
setTimeout(function(){
var touchGallery = document.getElementsByClassName('fancybox-wrap')[0];
var mc = new Hammer(touchGallery);
mc.on("panleft panright", function(ev) {
if (ev.type == "panleft") {
$("a.fancybox-next").trigger("click");
} else if (ev.type == "panright") {
$("a.fancybox-prev").trigger("click");
}
base._initSwipeGallery();
});
}, 500);
}
}
$(document).ready(function(){
haberdasherController.init();
});
});

ChartistJSF Extend

So, I'm using ChartistJSF (based on Chartist), the jsf version is kinda simples, so I'm trying to use some plugins offered in the javascript version, but I'm trying to figure out how to do this, because every chart "module" in JSF has a extend where I can put some extra configurations, but this one doesn't have. Can you guys help me?
Since 3.0, ChartistJSF supports plugins, here's an example of chartist-plugin-threshold:
xhtml
<ct:chart id="lineChart" type="line" model="#{chartDataBean.pluginsModel}"
plugins="myPlugins"
styleClass="example-plugin-threshold">
</ct:chart>
js
<script>
var myPlugins =
[
Chartist.plugins.ctThreshold({
threshold: 4
})
];
</script>
css
.example-plugin-threshold .ct-line {
stroke-dasharray: 5px;
animation: dashoffset 1s linear infinite;
}
.example-plugin-threshold.ct-chart .ct-series .ct-bar.ct-threshold-above,.example-plugin-threshold.ct-chart .ct-series .ct-line.ct-threshold-above,.example-plugin-threshold.ct-chart .ct-series .ct-point.ct-threshold-above {
stroke: #f05b4f;
}
.example-plugin-threshold.ct-chart .ct-series .ct-bar.ct-threshold-below,.example-plugin-threshold.ct-chart .ct-series .ct-line.ct-threshold-below,.example-plugin-threshold.ct-chart .ct-series .ct-point.ct-threshold-below {
stroke: #59922b;
}
.example-plugin-threshold.ct-chart .ct-series .ct-area.ct-threshold-above {
fill: #f05b4f;
}
.example-plugin-threshold.ct-chart .ct-series .ct-area.ct-threshold-below {
fill: #59922b;
}
#-webkit-keyframes dashoffset {
0% {
stroke-dashoffset: 0
}
100% {
stroke-dashoffset: -20px
}
}
#-moz-keyframes dashoffset {
0% {
stroke-dashoffset: 0
}
100% {
stroke-dashoffset: -20px
}
}
#-ms-keyframes dashoffset {
0% {
stroke-dashoffset: 0
}
100% {
stroke-dashoffset: -20px
}
}
#keyframes dashoffset {
0% {
stroke-dashoffset: 0
}
100% {
stroke-dashoffset: -20px
}
}
Result:

keyframe animation image layering

I am trying to have one image come into view behind another one. Is it possible to use z-index/opacity to accomplish this? Below is the code I'm referring to. I'm using the background-position property to move things in-out of view.
#-webkit-keyframes bannerAnimation {
0% {
background-position-x:
-240px,
-160px,
-240px,
0;
}
50% {
background-position-x:
-240px,
-45px,
-140px,
0;
}
100% {
background-position-x:
117px,
-65px,
117px,
0;
}
0%, 48% {
background-position-y:
-4000px,
0px,
480px,
0px;
}
50%, 100% {
background-position-y:
14px,
0px,
43px,
0px;
}
0% {
opacity:
0,
1,
0,
1;
}
50% {
opacity:
0,
1,
0,
1;
}
100% {
opacity:
1,
1,
1,
1;
}
}
#banner a#main .content {
background-image:
url('../images/95x27_headline_2x.png'),
url('../images/155x50_stephen_2x.png'),
url('../images/41x4_copy_2x.png'),
url('../images/320x50_bg_2x.png');
background-size:
95px 27px,
155px 50px,
41px 4px,
320px 50px;
background-position-y:
50px,
0px,
50px,
0px;
-webkit-animation: bannerAnimation 6s ease forwards;
to achieve what you are trying to do I would suggest using seperate divs for seperate images.
Then instead of animating background-position, try animating the z-index itself.
#keyframes move {
from { z-index: 0; transform: scale(1); }
to { z-index: 4; transform: scale(2.5); }
}
Check out this example on codepen.io to get you started in the right direction :)

Make "widget" for SVG-group in D3.js

I am using D3 to manipulate an SVG, that contains several "widgets" that have behavior and can be controlled eg via events. For instance I have a spinning fan. It should be possible to turn on and off the fan. I have been able to build that in D3, but not in an elegant way, and with all the code being global. What I want to end up with is something as below:
Creation of "widget", as known from jQuery:
d3.select('svg').append('g').attr('id', 'myFan').fan();
And then I would like to turn on and off with smth like the following, also as known from jQuery:
d3.select('#myFan').fan('start')
d3.select('#myFan').fan('stop')
Is it possible to achieve this in D3, ie to create such a "widget"?
Is there generally a different approach to such a problem, when using D3?
My current unelegant solution with global code:
Robert asked for this. Code at Codepen: link.
Javascript
var fan = d3.select('body')
.append('svg')
.attr('width', 200)
.attr('height', 200)
.append('g')
.attr('class', 'fan')
.attr('id', 'myFan')
.attr('transform', 'translate(75,75)')
// Static, background disc
fan.append('circle')
.attr('cx',0)
.attr('cy',0)
.attr('r',60)
// Dynamic, rotating path
var blade = fan.append('path')
.attr('d', 'M 0 0 L -30 15 L -60 0 Z L 30 -15 L 60 0 Z ')
.attr('transform', 'translate(50,50)')
.attr('transform', 'rotate(90)');
// Static, hub
fan.append('circle')
.attr('cx', 0)
.attr('cy', 0)
.attr('r', 10)
var rotation = 0; // degrees
var speed = 10; // degree per call
function rotate() {
rotation = (rotation + speed) % 360;
blade.attr('transform', 'rotate('+rotation+')')
}
setInterval(rotate, 100);
function stop() { speed = 0; }
function start() { speed = 10; }
var ctrlPanel = d3.select('body').append('div');
ctrlPanel.append('button').text('Start').on('click', start);
ctrlPanel.append('button').text('Stop').on('click', stop);
CSS
path {
fill: red;
strok: blue;
stroke-width: 3px;
}
.fan circle {
fill: lightgray;
stroke: black;
stroke-width: 3px;
}
.fan path {
fill: darkgray;
stroke: black;
stroke-width: 3px;
}

Can stroke-width on a SVG be animated?

I tried to animate the width of a SVG like this and it did not work
Normally I can have multiple lines, but can I make them thicker/thinner?
.swidth {
animation: hideshow 5s ease infinite;
}
#keyframes hideshow {
from { stroke-width="2"; }
to { stroke-width="6;"; }
}
It's CSS syntax inside #keyframes so something like:
#keyframes hideshow {
from { stroke-width: 2; }
to { stroke-width: 6; }
}

Resources