One day, by coincidence, I saw an article and was deeply fascinated by it. brucelyy: Learn another trick to be a beautiful woman (But it's 404 already)
Then spend a few days to encapsulate it, the level is limited, so the title is concise! Ugly!!! Version!!!
First of all, we use the picture of the goddess.
First, basic framework construction
Let's first look at how the basic framework works.
<!DOCTYPE HTML> <html> <head> <title>My Goddess</title> <style> html { overflow: hidden; } #wrapper { width: 40rem; height: 25rem; position: relative; margin: 20px auto; } #wrapper div { background-image: url("http://b-ssl.duitang.com/uploads/item/201801/14/20180114134621_auNRE.jpeg"); background-repeat: no-repeat; background-size: 40rem auto; position: absolute; width: 40rem; height: 40rem; } </style> </head> <body> <button id="button" type="button">Click on Beauty</button> <div id="wrapper"> <div></div> </div> </body> </html>
Now let's step by step analyze the main code functions:
html {overflow: hidden;}// jitter caused by hidden scrollbars
The key layout that can be achieved is the following code:
#wrapper div { background-image: url("http://b-ssl.duitang.com/uploads/item/201801/14/20180114134621_auNRE.jpeg"); background-repeat: no-repeat; background-size: 40rem auto; position: absolute; width: 40rem; height: 40rem; }
If the following fragmentation cannot be completed without absolute positioning,
From this, we can also find the current problems of the rudimentary version. First, we must use the background map to realize it.
The second problem caused by the background image: the size of height and width should be set
There's nothing else to say. Now the html + part comes out.
Second, Javascript implementation
In fact, the principle is not complicated, that is, to generate multiple small elements to locate screenshots separately, and then through the expansion, rotation, deformation, transparency and other effects to show in time difference. Here we directly use three attributes to control a class matching control effect.
Generating time difference:
// Generating Random Time Difference function Random(start, end) { return Math.random() * (end - start) + start; }
The effect is similar to Sprite image by splitting several small fragments and recording the current position to locate the image position.
// Divide several small pieces and record the current position to locate the position of the image, making a Sprite-like effect. for (var i = 0; i < r; i++) { for (var j = 0; j < c; j++) { var _div = document.createElement('div'); var _left = j * w, _top = i * h; _div.style.Text = 'width:' + w + 'px;height:' + h + 'px;left:' + _left + 'px;top:' + _top + 'px; opacity:0;background-position:' + (-_left) + 'px ' + (-_top) + 'px'; _div.style.transition = 'all ' + Random(1, 1.8) + 's ease'; _div.style.transform = 'perspective(800px) translate3d(' + Random(-200, 200) + 'px, ' + Random(-200, 200) + 'px,300px) rotate(' + Random(-90, 90) + 'deg) scale(' + Random(0, 2) + ')' box.appendChild(_div); } }
Because inserting separately in this way is too performance-intensive, I create a lot of insertion through characters.
It can also be found that the current problem of the rudimentary version is three: the performance loss is large, temporary ideas can consider canvas, but I do not study much, first use string to solve the problem;
Key styles of triggering:
#div.set div { opacity: 1 !important; transform: perspective(800px) translate3d(0px, 0px, 0px) rotate(0deg) scale(1) !important; -moz-transform: perspective(800px) translate3d(0px, 0px, 0px) rotate(0deg) scale(1) !important; -webkit-transform: perspective(800px) translate3d(0px, 0px, 0px) rotate(0deg) scale(1) !important; }
The good thing about this is that it's triggered by style control rather than js, which saves a lot of time.
Third, finally began to encapsulate
Here I am writing in more detail on the basis of improving my personal writing level and friendly attitude towards novices. The veteran can just skip to the bottom of the code.
Now you should all understand the principle, or to save time, I directly encapsulated it with jQuery, the conventional steps first write an outer layer:
$(function($) { //Default configuration var defaults = { }; }(jQuery));
Then the previous time difference function can be attached to the kernel directly as a plug-in of the global function in jQuery. Conventional configurations can be: trigger elements, number of columns, animation time, delay time and class names to control animation.
$(function ($) { //Default configuration var defaults = { className: 'explode',//Control class name button: null, //Trigger button lines: 5, //Segmented rows rows: 5, //Segmented column delay: 0, //ms, automatic execution time of animation, default 300 milliseconds, 0 is not triggered time: [1, 1.8], //Animation Time Range }; $.fn.explode = function (options) { //Keeping this pointing, there is no need to wrap this in a $number, such as $(this), because this is already a jQuery object. var $self = this, _explode = { //Initialization init: function () { //conditions for execution options = $.extend(defaults, options); }, } // Generating Random Time Difference $.Random = function (start, end) { return Math.random() * (end - start) + start; } }(jQuery))
There are some code snippets worth mentioning: var $self = this, which I thought should be var $self = this. In fact, this is to point to trigger objects, such as $(' div').explode().
So here this ==$('#div')?
Actually not. Even if the content is the same, it actually points to different stacks, so they are not the same. For more details, please refer to the notes I wrote earlier. Basic Types and Reference Types
This is a configurable item. If you don't know how to use it, you can Baidu it. Generally speaking, it will merge into an object and cover the front with the same configuration.
options = $.extend(defaults, options);
The original batch insertion dom element is modified as follows:
// Generating DOM createDom: function() { var i = 0, j = 0, width = $self.width(), height = $self.height(), w = width / options.lines, h = height / options.rows, str = ''; // Cutting debris for (; i < options.rows; i++) { for (j = 0; j < options.lines; j++) { //Fill in screenshot animation var _left = j * w, _top = i * h; str += "<div style='width:" + w + "px;\ height:" + h + "px;\ left:" + _left + "px;\ top:" + _top + "px;\ opacity:0;\ background-position:" + (-_left) + "px " + (-_top) + "px;\ transition:all " + $.Random(options.time[0], options.time[1]) + "s ease;\ transform:perspective(" + width + "px) translate3d(" + $.Random(-w, w) + "px, " + $.Random(-w, w) + "px,300px) rotate(" + $.Random(-90, 90) + "deg) scale(" + $.Random(0, 2) + ")'></div>" } }; return str; }
Because there are no difficulties, let's not say, I believe everyone can see clearly.
Considering that plug-ins are best able to solve most of the problems, users can complete the effect as long as they call, so I add the control style dynamically.
//Add as Style addStyle: function () { var $style = $('style'), _w = $self.width(), _style = '#wrapper div {background-image:url(' + $self.attr('data-img') + ')}\ #wrapper.' + options.className + ' div {\ opacity: 1!important;\ transform: perspective(' + _w + ') translate3d(0px, 0px, 0px) rotate(0deg) scale(1)!important;\ -moz-transform: perspective(' + _w + ') translate3d(0px, 0px, 0px) rotate(0deg) scale(1)!important;\ -webkit-transform: perspective(' + _w + ') translate3d(0px, 0px, 0px) rotate(0deg) scale(1)!important;\ }'; //Added text to existing style areas, otherwise added $style.length ? $style.append(_style) : $('<style />') .text(_style) .appendTo('body'); }
And the trigger elements mentioned above, bind and unbind
//binding bind: function() { //If there are trigger elements if(options.button) $(options.button).click(function() { $self.toggleClass(options.className); }) }, //Remove bindings destroy: function() { $(options.button).unbind('click') },
Adding an automated execution is almost like a chain call, so init changes to this
//Initialization init: function() { //conditions for execution options = $.extend(defaults, options); //Add Homing Style this.addStyle(); //Batch Rendering DOM $self.append(this.createDom()); //binding this.bind(); //If there is an automatic execution requirement, default 300 if(options.delay) setTimeout(function() { $self.addClass(options.className); }, options.delay) //call chaining return this; },
The invocation method is as follows:
$(function() { $('#wrapper').explode({ className: 'explode', button: $('#button'), lines: 5, rows: 5, delay: 300, time: [1, 2] }); })
Well, that's all for the rudimentary version. Here's the complete code:
<!DOCTYPE HTML> <html> <head> <title>Beauty</title> <style> html { overflow: hidden; } #wrapper { width: 500px; height: 500px; position: relative; margin: 20px auto; } #wrapper div { background-repeat: no-repeat; background-size: 40rem auto; position: absolute; width: 100px; height: 100px; } #button{ position: relative; z-index: 10; } </style> </head> <body> <button id="button" type="button">Click on Beauty</button> <div id="wrapper" data-img='http://b-ssl.duitang.com/uploads/item/201801/14/20180114134621_auNRE.jpeg'></div> <script src="https://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <script> $(function ($) { //Default configuration var defaults = { className: 'explode', //Control class name button: null, //Trigger button lines: 5, //Segmented rows rows: 5, //Segmented column delay: 0, //ms, automatic execution time of animation, default 300 milliseconds, 0 is not triggered time: [ 1, 1.8 ], //Animation Time Range }; $.fn.explode = function (options) { //Keeping this pointing, there is no need to wrap this in a $number, such as $(this), because this is already a jQuery object. var $self = this, _explode = { //Initialization init: function () { //conditions for execution options = $.extend(defaults, options); //Add Homing Style this.addStyle(); //Batch Rendering DOM $self.append(this.createDom()); //binding this.bind(); //If there is an automatic execution requirement, default 300 if (options.delay) setTimeout(function () { $self.addClass(options.className); }, options.delay) //call chaining return this; }, //binding bind: function () { //If there are trigger elements if (options.button) $(options.button).click(function () { $self.toggleClass(options.className); }) }, //Remove bindings destroy: function () { $(options.button).unbind('click') }, //Generating DOM createDom: function () { var i = 0, j = 0, width = $self.width(), height = $self.height(), w = width / options.lines, h = height / options.rows, str = ''; //Cutting debris for (; i < options.rows; i++) { for (j = 0; j < options.lines; j++) { //Fill in screenshot animation var _left = j * w, _top = i * h; str += "<div style='width:" + w + "px;\ height:" + h + "px;\ left:" + _left + "px;\ top:" + _top + "px;\ opacity:0;\ background-position:" + (-_left) + "px " + (-_top) + "px;\ transition:all " + $.Random(options.time[0], options.time[1]) + "s ease;\ transform:perspective(" + width + "px) translate3d(" + $.Random(-w, w) + "px, " + $.Random(-w, w) + "px,300px) rotate(" + $.Random(-90, 90) + "deg) scale(" + $.Random(0, 2) + ")'></div>" } }; return str; }, //Add as Style addStyle: function () { var $style = $('style'), _w = $self.width(), _style = '#wrapper div {background-image:url(' + $self.attr('data-img') + ')}\ #wrapper.' + options.className + ' div {\ opacity: 1!important;\ transform: perspective(' + _w + ') translate3d(0px, 0px, 0px) rotate(0deg) scale(1)!important;\ -moz-transform: perspective(' + _w + ') translate3d(0px, 0px, 0px) rotate(0deg) scale(1)!important;\ -webkit-transform: perspective(' + _w + ') translate3d(0px, 0px, 0px) rotate(0deg) scale(1)!important;\ }'; //Added text to existing style areas, otherwise added $style.length ? $style.append(_style) : $('<style />') .text(_style) .appendTo('body'); } } //Automatic initialization _explode.init(); } //Random Range $.Random = function (start, end) { return Math.random() * (end - start) + start; } }(jQuery)); </script> <script> $(function () { $('#wrapper').explode({ className: 'explode', button: $('#button'), lines: 5, rows: 5, delay: 300, time: [1, 2] }); }) </script> </body> </html>
The effect comes out, and there are many disadvantages.
Question 4: Fragments do not disappear, but are hidden. It is easy to hide the interactive events of other elements, such as the buttons in the case.
Question 5: Can it be realized that in the actual website, the image fragments enter and slide down will trigger the image execution under the view, more likely to be combined with the lazy loading plug-in.
Well, for the time being, I think so much about it. Although my ability is not strong enough, it's still good to have ideas. I think it will be better if I improve it slowly in the future. Some people can communicate with each other.