UNPKG

animated_brackets

Version:
215 lines (155 loc) 6.26 kB
'use strict'; /* animatedBrackets Author: lemehovskiy */ ;(function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { define(['jquery'], factory); } else if (typeof exports !== 'undefined') { module.exports = factory(require('jquery')); } else { factory(jQuery); } })(function ($) { $.fn.animatedBrackets = function (options) { var settings = $.extend({ points: ['0 20, 0 0, 100 0, 100 20', '100 80, 100 100, 0 100, 0 80'], color: '#ffffff', stroke_width: 10, duration: 1, delay: 1 }, options); $(this).each(function () { var $this = $(this), $this_width = 0, $this_height = 0, brackets_config = [], is_inited = false, is_animated = false, svgElement = $(document.createElementNS("http://www.w3.org/2000/svg", "svg")); //generate brackets config settings.points.forEach(function (points_str) { var brackets_points = points_str.split(', '); var bracket_points_arr = []; brackets_points.forEach(function (item) { bracket_points_arr.push(item.split(' ')); }); brackets_config.push({ points: bracket_points_arr }); }); $this.append(svgElement); $this.css({ position: 'relative' }); svgElement.css({ width: '100%', height: '100%', position: 'absolute', left: 0, top: 0, overflow: 'visible' }); brackets_config.forEach(function (bracket) { bracket.element = $(document.createElementNS("http://www.w3.org/2000/svg", 'polyline')); svgElement.append(bracket.element); }); $(window).on('load resize', function () { $this_width = $this.outerWidth(); $this_height = $this.outerHeight(); draw_brackets(); }); $(window).on('load scroll resize', function () { if (is_inited && $this.isOnScreen(.5, .5) && !is_animated) { animate_brackets({ path: $this.find('polyline'), duration: settings.duration, delay: settings.delay }); is_animated = true; } }); function draw_brackets() { brackets_config.forEach(function (bracket) { draw_polyline({ element: bracket.element, points: bracket.points, element_width: $this_width, element_height: $this_height, color: settings.color, stroke_width: settings.stroke_width }); if (!is_animated) { set_dash({ element: bracket.element }); } }); is_inited = true; } }); function set_dash(settings) { var element = settings.element; var length = get_path_length(element.get(0)); element.attr("stroke-dasharray", length); element.attr("stroke-dashoffset", length); } function get_path_length(path) { var totalLength = 0; var prevPos = void 0; var polyline = path; for (var i = 0; i < polyline.points.numberOfItems; i++) { var pos = polyline.points.getItem(i); if (i > 0) { totalLength += Math.sqrt(Math.pow(pos.x - prevPos.x, 2) + Math.pow(pos.y - prevPos.y, 2)); } prevPos = pos; } return totalLength; } function animate_brackets(settings) { var timeline = new TimelineLite(); timeline.staggerTo(settings.path, settings.duration, { attr: { 'stroke-dashoffset': 0 } }, settings.delay); } function draw_polyline(settings) { var element = settings.element; var points = settings.points; var points_str = ''; points.forEach(function (item) { points_str += settings.element_width / 100 * item[0] + ", " + settings.element_height / 100 * item[1] + " "; }); element.attr("points", points_str); element.attr("style", "stroke:" + settings.color + "; stroke-width:" + settings.stroke_width + "; fill:none"); //Set path's data } }; $.fn.isOnScreen = function (x, y) { if (x == null || typeof x == 'undefined') x = 1; if (y == null || typeof y == 'undefined') y = 1; var win = $(window); var viewport = { top: win.scrollTop(), left: win.scrollLeft() }; viewport.right = viewport.left + win.width(); viewport.bottom = viewport.top + win.height(); var height = this.outerHeight(); var width = this.outerWidth(); if (!width || !height) { return false; } var bounds = this.offset(); bounds.right = bounds.left + width; bounds.bottom = bounds.top + height; var visible = !(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom); if (!visible) { return false; } var deltas = { top: Math.min(1, (bounds.bottom - viewport.top) / height), bottom: Math.min(1, (viewport.bottom - bounds.top) / height), left: Math.min(1, (bounds.right - viewport.left) / width), right: Math.min(1, (viewport.right - bounds.left) / width) }; return deltas.left * deltas.right >= x && deltas.top * deltas.bottom >= y; }; });