Гмстограмма с анимацией
Здравствуйте!
Пытаюсь вытащить из работающего сайта на wordpress блок с горизонтальной диаграммой:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script src="http://code.jquery.com/jquery-1.8.3.js"></script>
<style>
.digram-line-box { background-color: #f4f6f7;}
.diagram-wrapper.style-1 .digram-line-box .skill-line {margin-right: 0px;}
.diagram-wrapper.style-1 .digram-line-box .skill-amount {margin-top: -30px;}
.diagram-wrapper.style-1 .digram-line-box .skill-element {padding-top: 14px;}
.diagram-item{margin-bottom:1.421em}
.skill-element+.skill-element{margin:8px 0 0 0}
.skill-title{font-size:89.5%;line-height:1.421;margin:0 0 5px 0}
.skill-amount{float:right;font-size:126.3%;margin-top:-11px}
.skill-line{font-size:0;line-height:1;height:10px;margin-right:55px}
.skill-line div{display:inline-block;font-size:0;line-height:1;height:10px}
.skill-line div.animation{-moz-transition:width 1.6s cubic-bezier(0.165, 0.84, 0.44, 1);-ms-transition:width 1.6s cubic-bezier(0.165, 0.84, 0.44, 1);-o-transition:width 1.6s cubic-bezier(0.165, 0.84, 0.44, 1);-webkit-transition:width 1.6s cubic-bezier(0.165, 0.84, 0.44, 1);transition:width 1.6s cubic-bezier(0.165,0.84,0.44,1)}
.diagram-summary{font-size:89.5%;line-height:1.471;margin:0 0 0.766667em 0}
.widget .diagram-summary{font-size:100%}
.diagram-summary-text{margin:0 0 0.766667em 0}
</style>
</head>
<body>
<div class="diagram-item">
<div class="diagram-wrapper style-1">
<div class="" >
<div class="digram-line-box " >
<div class="skill-element">
<div class="skill-title">Оптимизация </div>
<div class="clearfix">
<div style="color:#464c5c" class="skill-amount">0%</div>
<div class="skill-line">
<div data-amount="98" style="background: #464c5c;"></div>
</div>
</div>
</div>
<div class="skill-element">
<div class="skill-title">Кроссплатформенность </div>
<div class="clearfix">
<div style="color:#6d747a" class="skill-amount">0%</div>
<div class="skill-line">
<div data-amount="100" style="background: #6d747a;">
</div>
</div>
</div>
</div>
<div class="skill-element">
<div class="skill-title">Удобство </div>
<div class="clearfix">
<div style="color:#8c8274" class="skill-amount">0%</div>
<div class="skill-line">
<div data-amount="99" style="background: #8c8274;">
</div>
</div>
</div>
</div>
<div class="skill-element">
<div class="skill-title">Дизайн </div>
<div class="clearfix">
<div style="color:#d2c6b4" class="skill-amount">0%</div>
<div class="skill-line">
<div data-amount="99" style="background: #d2c6b4;">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
(function($) {
var prefixes = 'Webkit Moz ms Ms O'.split(' ');
var docElemStyle = document.documentElement.style;
function getStyleProperty( propName ) {
if ( !propName ) {
return;
}
// test standard property first
if ( typeof docElemStyle[ propName ] === 'string' ) {
return propName;
}
// capitalize
propName = propName.charAt(0).toUpperCase() + propName.slice(1);
// test vendor specific properties
var prefixed;
for ( var i=0, len = prefixes.length; i < len; i++ ) {
prefixed = prefixes[i] + propName;
if ( typeof docElemStyle[ prefixed ] === 'string' ) {
return prefixed;
}
}
}
var transitionProperty = getStyleProperty('transition');
var transitionEndEvent = {
WebkitTransition: 'webkitTransitionEnd',
MozTransition: 'transitionend',
OTransition: 'otransitionend',
transition: 'transitionend'
}[ transitionProperty ];
function LineDiagram(element) {
this.el = element;
this.$el = jQuery(element);
this.start();
}
LineDiagram.prototype = {
start: function() {
if (!this.$el.hasClass('digram-line-box')) return;
this.initTimer();
var diagram_lines_queue = [];
jQuery('.skill-element', this.$el).each(function () {
diagram_lines_queue.push(jQuery(this));
});
this.showLine(diagram_lines_queue, true);
},
showLine: function(queue, first) {
var self = this,
$skill = queue.shift();
if ($skill == null || $skill == undefined) {
return;
}
function thegem_show_digram_line_animation() {
var $progress = $('.skill-line div', $skill),
$skillAmount = $('.skill-amount', $skill),
amount = parseFloat($progress.data('amount'));
$progress.addClass('animation').css('width', amount + '%');
jQuery({countNum: 0}).animate({countNum: amount}, {
duration: 1600,
easing:'easeOutQuart',
step: function() {
var count = parseFloat(this.countNum);
var pct = Math.ceil(count) + '%';
$skillAmount.html(pct);
}
});
self.showLine(queue, false);
}
if (first) {
thegem_show_digram_line_animation();
} else {
this.startTimer(thegem_show_digram_line_animation);
}
},
initTimer: function() {
var self = this;
this.timer = this.$el.data('timer');
this.timerCallback = function() {};
$(this.timer).bind(transitionEndEvent, function(event) {
self.timerCallback();
});
},
startTimer: function(callback) {
var self = this;
this.timerCallback = callback;
if (this.timer.className.indexOf('start-timer') != -1) {
this.timer.className = this.timer.className.replace(' start-timer', '');
} else {
this.timer.className += ' start-timer';
}
}
};
jQuery.fn.thegem_start_line_digram = function() {
return new LineDiagram(this.get(0));
}
})(jQuery);
function thegem_show_diagram_line_mobile($box) {
jQuery('.skill-element', $box).each(function () {
jQuery('.skill-line div', this).width(jQuery('.skill-line div', this).data('amount') + '%');
});
}
function thegem_start_line_digram(element) {
jQuery(element).thegem_start_line_digram();
}
jQuery('.digram-line-box').each(function () {
var self = this;
var timer = document.createElement('div');
timer.className = 'diagram-line-timer-element';
document.body.appendChild(timer);
timer.className += ' start-timer';
jQuery(this).data('timer', timer);
//jQuery('.skill-element .skill-amount', this).html('0%');
jQuery(document).ready(function() {
if (!jQuery(self).hasClass('lazy-loading-item') || window.gemSettings.lasyDisabled)
jQuery(self).thegem_start_line_digram();
});
});
</script>
</body>
</html>
Но что-то не получается... в консоле вижу ошибку "Uncaught TypeError: jQuery.easing[this.easing] is not a function"... Где ошибка? ( |
easing Ключевое слово (строка), которое определяет кривую скорости для анимации (используется математическая функция - кубическая кривая Безье). Без использования внешних плагинов имеет только два значения - linear (эффект анимации с одинаковой скоростью от начала до конца) и swing (эффект анимации имеет медленный старт и медленное окончание, но скорость увеличивается в середине анимации). Значение по умолчанию swing.
|
да, я сейчас добавил
<script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.5/jquery-ui.min.js'></script> заработала только первая диаграма из четырех... и анимации линии даже на ней нет (но это я возможно с scc "недотумкал") |
Igorsrt,
К какому/каким объектам вы применяете анимацию?
jQuery({countNum: 0}).animate(
|
Цитата:
|
Цитата:
.skill-line div{display:inline-block;font-size:0;line-height:1;height:10px;width : 0;} |
Цитата:
self.showLine(queue, true); |
Igorsrt,
и того
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
jQuery.easing.easeOutQuart = function(x, t, b, c, d) {
return -c * (t /= d) * (t - 2) + b
}
</script>
<style>
.digram-line-box { background-color: #f4f6f7;}
.diagram-wrapper.style-1 .digram-line-box .skill-line {margin-right: 0px;}
.diagram-wrapper.style-1 .digram-line-box .skill-amount {margin-top: -30px;}
.diagram-wrapper.style-1 .digram-line-box .skill-element {padding-top: 14px;}
.diagram-item{margin-bottom:1.421em}
.skill-element+.skill-element{margin:8px 0 0 0}
.skill-title{font-size:89.5%;line-height:1.421;margin:0 0 5px 0}
.skill-amount{float:right;font-size:126.3%;margin-top:-11px}
.skill-line{font-size:0;line-height:1;height:10px;margin-right:55px}
.skill-line div{display:inline-block;font-size:0;line-height:1;height:10px;width : 0;}
.skill-line div.animation{-moz-transition:width 1.6s cubic-bezier(0.165, 0.84, 0.44, 1);-ms-transition:width 1.6s cubic-bezier(0.165, 0.84, 0.44, 1);-o-transition:width 1.6s cubic-bezier(0.165, 0.84, 0.44, 1);-webkit-transition:width 1.6s cubic-bezier(0.165, 0.84, 0.44, 1);transition:width 1.6s cubic-bezier(0.165,0.84,0.44,1)}
.diagram-summary{font-size:89.5%;line-height:1.471;margin:0 0 0.766667em 0}
.widget .diagram-summary{font-size:100%}
.diagram-summary-text{margin:0 0 0.766667em 0}
</style>
</head>
<body>
<div class="diagram-item">
<div class="diagram-wrapper style-1">
<div class="" >
<div class="digram-line-box " >
<div class="skill-element">
<div class="skill-title">Оптимизация </div>
<div class="clearfix">
<div style="color:#464c5c" class="skill-amount">0%</div>
<div class="skill-line">
<div data-amount="98" style="background: #464c5c;"></div>
</div>
</div>
</div>
<div class="skill-element">
<div class="skill-title">Кроссплатформенность </div>
<div class="clearfix">
<div style="color:#6d747a" class="skill-amount">0%</div>
<div class="skill-line">
<div data-amount="100" style="background: #6d747a;">
</div>
</div>
</div>
</div>
<div class="skill-element">
<div class="skill-title">Удобство </div>
<div class="clearfix">
<div style="color:#8c8274" class="skill-amount">0%</div>
<div class="skill-line">
<div data-amount="99" style="background: #8c8274;">
</div>
</div>
</div>
</div>
<div class="skill-element">
<div class="skill-title">Дизайн </div>
<div class="clearfix">
<div style="color:#d2c6b4" class="skill-amount">0%</div>
<div class="skill-line">
<div data-amount="99" style="background: #d2c6b4;">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
(function($) {
var prefixes = 'Webkit Moz ms Ms O'.split(' ');
var docElemStyle = document.documentElement.style;
function getStyleProperty( propName ) {
if ( !propName ) {
return;
}
// test standard property first
if ( typeof docElemStyle[ propName ] === 'string' ) {
return propName;
}
// capitalize
propName = propName.charAt(0).toUpperCase() + propName.slice(1);
// test vendor specific properties
var prefixed;
for ( var i=0, len = prefixes.length; i < len; i++ ) {
prefixed = prefixes[i] + propName;
if ( typeof docElemStyle[ prefixed ] === 'string' ) {
return prefixed;
}
}
}
var transitionProperty = getStyleProperty('transition');
var transitionEndEvent = {
WebkitTransition: 'webkitTransitionEnd',
MozTransition: 'transitionend',
OTransition: 'otransitionend',
transition: 'transitionend'
}[ transitionProperty ];
function LineDiagram(element) {
this.el = element;
this.$el = jQuery(element);
this.start();
}
LineDiagram.prototype = {
start: function() {
if (!this.$el.hasClass('digram-line-box')) return;
this.initTimer();
var diagram_lines_queue = [];
jQuery('.skill-element', this.$el).each(function () {
diagram_lines_queue.push(jQuery(this));
});
this.showLine(diagram_lines_queue, true);
},
showLine: function(queue, first) {
var self = this,
$skill = queue.shift();
if ($skill == null || $skill == undefined) {
return;
}
function thegem_show_digram_line_animation() {
var $progress = $('.skill-line div', $skill),
$skillAmount = $('.skill-amount', $skill),
amount = parseFloat($progress.data('amount'));
$progress.addClass('animation').css('width', amount + '%');
jQuery({countNum: 0}).animate({countNum: amount}, {
duration: 1600,
easing:'easeOutQuart',
step: function() {
var count = parseFloat(this.countNum);
var pct = Math.ceil(count) + '%';
$skillAmount.html(pct);
}
});
self.showLine(queue, true);
}
if (first) {
thegem_show_digram_line_animation();
} else {
this.startTimer(thegem_show_digram_line_animation);
}
},
initTimer: function() {
var self = this;
this.timer = this.$el.data('timer');
this.timerCallback = function() {};
$(this.timer).bind(transitionEndEvent, function(event) {
self.timerCallback();
});
},
startTimer: function(callback) {
var self = this;
this.timerCallback = callback;
if (this.timer.className.indexOf('start-timer') != -1) {
this.timer.className = this.timer.className.replace(' start-timer', '');
} else {
this.timer.className += ' start-timer';
}
}
};
jQuery.fn.thegem_start_line_digram = function() {
return new LineDiagram(this.get(0));
}
})(jQuery);
function thegem_show_diagram_line_mobile($box) {
jQuery('.skill-element', $box).each(function () {
jQuery('.skill-line div', this).width(jQuery('.skill-line div', this).data('amount') + '%');
});
}
function thegem_start_line_digram(element) {
jQuery(element).thegem_start_line_digram();
}
jQuery('.digram-line-box').each(function () {
var self = this;
var timer = document.createElement('div');
timer.className = 'diagram-line-timer-element';
document.body.appendChild(timer);
timer.className += ' start-timer';
jQuery(this).data('timer', timer);
//jQuery('.skill-element .skill-amount', this).html('0%');
jQuery(document).ready(function() {
if (!jQuery(self).hasClass('lazy-loading-item') || window.gemSettings.lasyDisabled)
jQuery(self).thegem_start_line_digram();
});
});
</script>
</body>
</html>
|
Цитата:
|
Еще один вопрос возник: Как заставить анимацию этой диаграммы срабатывать при прокрутке страницы (она у меня оказалась ниже первого экрана)?
|
var fl = true;
onscroll = function(){
if(document.querySelector("селектор_элемента_с_анимацией").getBoundingClientRect().top - innerHeight < 0 && fl) {
fl = false;
//сюда запуск анимации
}
};
если запуск нужен ниже, вместо 0 свою цифру -n |
Разве вместо такого сложного и трудно поддерживаемого набора элементов не достаточно было бы использовать только 4 элемента <meter>?
j0hnik, у вас всё время, пока крутишь и видишь элемент, запускается анимация |
Malleys,
поправил |
Анимация запускается каждый раз, как только элемент входит в область видимости + только 4 <meter>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.skills { margin: 125vh 0; }
body::before { content: "Крути вниз!"; }
.skill {
width: 100%;
background: #eee;
padding-top: 2em;
display: flex;
flex-flow: wrap;
}
.skill .level {
flex: 1;
text-align: right;
font-size: 125%;
}
.skill meter {
width: 100%;
background: transparent;
}
.skill meter::-webkit-meter-bar {
background: transparent;
border: 0; /* убирает рамку в IE */
}
.skill meter::-moz-meter-bar {
background: currentColor;
}
.skill meter::-webkit-meter-optimum-value {
background: currentColor;
}
</style>
</head>
<body>
<section class="skills">
<meter min="0" max="100" value="98" style="color: #464c5c" title="Оптимизация"></meter>
<meter min="0" max="100" value="100" style="color: #6d747a" title="Кроссплатформенность"></meter>
<meter min="0" max="100" value="99" style="color: #8c8274" title="Удобство"></meter>
<meter min="0" max="100" value="99" style="color: #d2c6b4" title="Дизайн"></meter>
</section>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
jQuery.easing.easeOutQuart = function(x, t, b, c, d) {
return -c * (t /= d) * (t - 2) + b
};
jQuery(".skills meter").each(function(index, { value, title, style }) {
const descr = jQuery(`<span class="title">${title}</span>`);
const level = jQuery(`<span class="level" style="color: ${style.color}"></span>`);
const skill = jQuery(`<section class="skill"></section>`);
skill.append(descr, level);
$(this).replaceWith(skill);
skill.append(this);
document.addEventListener("meter:animate", () => jQuery({ value: 0 }).animate({ value }, {
duration: 1600,
easing: "easeOutQuart",
step: value => {
this.value = value;
level.text(`${value | 0}%`);
}
}));
});
let _isInView = false;
onscroll = () => {
const rect = document.querySelector(".skills").getBoundingClientRect();
const y = rect.bottom / (innerHeight + rect.bottom - rect.top);
const isInView = y > 0 && y < 1;
if(_isInView !== isInView) {
_isInView = isInView;
if(isInView)
document.dispatchEvent(new Event("meter:animate", { bubbles: true }));
}
};
</script>
</body>
</html>
|
Malleys,
:thanks: |
О, прикольно.. А что такое этот <meter> (раньше не видел такого тега). Он везде будет работать?
|
а, все-таки, может лучше "по старинке": куда что добавить в первоначальный скрипт, что бы он срабатывал при прокрутке до блока с диаграммой один раз? :)
|
Igorsrt,
тогда мой пост смотрите |
Цитата:
|
анимация чисел в зоне видимости гистограмма jquery
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
<style type="text/css">
.meter {
width: 100%;
height: 8px;
color: #fff ;
text-align: center;
margin: 30px 0;
position: relative;
}
.meter:after {
font-size: 18px;
content: attr(data-max);
color: #000;
position: absolute;
right: 5px;
top: -20px;
}
.meter:before {
font-size: 18px;
content: attr(data-title);
color: #000;
position: absolute;
left: 5px;
top: -20px;
}
p {
height: 2000px;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$(function() {
jQuery.easing.easeOutQuart = function(x, t, b, c, d) {
return -c * (t /= d) * (t - 2) + b
};
var num = $(".meter");
var duration = 1200;
num.each(function(indx, el) {
var max = $(el).data("max");
var color = $(el).data("color");
var visibility = checkViewport(el);
$(el).on("animeNum", function() {
$({
n: 0
}).animate({
n: max
}, {
easing: "easeOutQuart",
duration: duration,
step: function(now, fx) {
now |= 0;
now += "%";
var gradient = "linear-gradient(to right, " + color + " , " + color + " " + now + ", #FFFFFF " + now + ")";
$(el).attr("data-max", now).css({
"backgroundImage": gradient
})
}
})
}).data("visibility", visibility);
visibility && $(el).trigger("animeNum")
});
function checkViewport(elem) {
var rect = elem.getBoundingClientRect();
var y = rect.bottom / (innerHeight + rect.bottom - rect.top);
var isInView = y > 0 && y < 1;
return isInView
}
jQuery.fn.scrollComplete = function(fn, ms) {
var timer = null;
this.scroll(function() {
if (timer) clearTimeout(timer);
timer = setTimeout(fn, ms)
})
};
$(window).scrollComplete(function() {
num.each(function(indx, el) {
var visibility = checkViewport(el);
el = $(el);
var old = el.data("visibility");
old != visibility && el.data("visibility", visibility) && !old && el.trigger("animeNum")
})
},
100)
});
</script>
</head>
<body>
<p></p>
<div class="meter" data-max="98" data-title="Оптимизация" data-color="#464c5c"></div>
<div class="meter" data-max="100" data-title="Кроссплатформенность" data-color="#6d747a"></div>
<div class="meter" data-max="99" data-title="Удобство" data-color="#8c8274"></div>
<div class="meter" data-max="99" data-title="Дизайн" data-color="#d2c6b4"></div>
<p></p>
</body>
</html>
|
рони,
мне в этом варианте не нравится, что скрипт с анимацией каждый раз заново запускается при прокрутке "вверх-вниз"...мне бы хотелось что бы один раз после попадания в зону видимости сработала анимация и все... или я может недопонимаю чего-то опять |
Цитата:
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
<style type="text/css">
.meter {
width: 100%;
height: 8px;
color: #fff ;
text-align: center;
margin: 30px 0;
position: relative;
}
.meter:after {
font-size: 18px;
content: attr(data-max);
color: #000;
position: absolute;
right: 5px;
top: -20px;
}
.meter:before {
font-size: 18px;
content: attr(data-title);
color: #000;
position: absolute;
left: 5px;
top: -20px;
}
p {
height: 2000px;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$(function() {
jQuery.easing.easeOutQuart = function(x, t, b, c, d) {
return -c * (t /= d) * (t - 2) + b
};
var num = $(".meter");
var duration = 1200;
num.each(function(indx, el) {
var max = $(el).data("max");
var color = $(el).data("color");
$(el).on("animeNum", function() {
$({
n: 0
}).delay(indx * 200).animate({
n: max
}, {
easing: "easeOutQuart",
duration: duration,
step: function(now, fx) {
now |= 0;
now += "%";
var gradient = "linear-gradient(to right, " + color + " , " + color + " " + now + ", #FFFFFF " + now + ")";
$(el).attr("data-max", now).css({
"backgroundImage": gradient
})
}
})
})
});
function checkViewport(elem) {
var rect = elem.getBoundingClientRect();
var y = rect.bottom / (innerHeight + rect.bottom - rect.top);
var isInView = y > 0 && y < 1;
return isInView
}
function visibility()
{
return $.makeArray(num).some(checkViewport)
}
visibility() ? num.trigger("animeNum") :
$(window).scroll(function anime() {
visibility() && num.trigger("animeNum") && $(window).off("scroll", anime)
})
});
</script>
</head>
<body>
<p></p>
<div class="meter" data-max="98" data-title="Оптимизация" data-color="#464c5c"></div>
<div class="meter" data-max="100" data-title="Кроссплатформенность" data-color="#6d747a"></div>
<div class="meter" data-max="99" data-title="Удобство" data-color="#8c8274"></div>
<div class="meter" data-max="99" data-title="Дизайн" data-color="#d2c6b4"></div>
<p></p>
</body>
</html>
|
рони,
благодарю, именно так и хотел ) |
рони,
блин, только я хочу еще что бы полоски с задержкой анимировались (т.е. первая полоска сразу, вторая через 0.2s, третья через 0.4s и т.д.)... в прошлом варианте я через css это смог сделать (transition-delay)... А здесь как? |
Цитата:
}).delay(indx * 200).animate({ |
супер! спасибо
|
| Часовой пояс GMT +3, время: 05:15. |