Let’s introduce the photo wall renderings I realized according to the online video explanation.
The final effect is as follows:
•When a picture is clicked, the picture moves to the middle area and zooms in. When the picture is clicked, the front and back sides are switched to display.
• When a certain image is clicked, the positions of all images are randomly reordered
•When a control button is clicked, the corresponding picture is displayed in the middle, and the control button changes the corresponding style. When a control button is clicked continuously, the picture will switch the front and back side with the click of the button
VCD decomposition of the entire effect, as shown in the figure below:
Decompose cases in a way that computers can understand.
•View Vision: HTML + css Basic Interface Template
•Controller: Javascript content processing, event processing
•Data data: data.js is not necessary, helps understand
Data data is very commonly used. If you write the content to the View, that is, HTML, you have to modify the HTML when you want to change the content, but if you use VCD, you only need to modify the data part. At the same time, the general data part is generated by the background, so such a replacement is more convenient. The posters in this case are all generated by templates plus data.
View section
The effect area is decomposed into the following three parts:
•The current poster area
Horizontal and vertical center
Allows to be displayed & flipped by <Control Bar Button>
•Left and left storage areas
Divide into left and right areas by <the current poster area>
It is to store other posters
Each poster is randomly positioned and angled
•Control bar area
Control & display the corresponding poster
Flip toggle <Current display poster> front and back
The implemented html code is as follows:
<body onselectstart = 'return false;'><!-- here to prevent the text of the page from being selected --> <!-- 2. Rewrite the view as a template string --> <div id="wrap"> <!-- div.photo is responsible for translation and rotation --> <div onclick = "turn(this)" id="photo_{{index}}"> <!-- div.photo-wrap is responsible for flipping the front and back --> <div> <p><img src="photo/{{img}}"></p> <p>{{caption}}</p> </div> <div> <p>{{desc}}</p> </div> </div> </div> </div> </div> </div> </div>Here, {{img}}, {{caption}}, and {{desc}} are template strings, and the data part will be corresponding but replaced later.
The style of the view part is as follows:
<style type="text/css"> *{ padding:0; margin:0; } body{ background-color:#ffff; color:#555; font-family:'Avenir Next','Lantinghei SC'; font-size:14px; -moz-font-smoothing:antialiased; -webkit-font-smoothing:antialiased;/*Font smooth*/ } .wrap{ //The image area is vertically centered in the body width:100%; height:900px; position:absolute; /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- top:50%; margin-top:-300px; /*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ /*Because each poster is randomly positioned using top and left, set position to absolute*/ position:absolute; z-index:1; box-shadow:0 0 1px rgba(0,0,0,.01); /*transform:rotateY(30deg);*/ -moz-transition:all .6s; /*Let the poster move to produce animation effect*/ -webkit-transition:all .6s; } .photo .side{ width:100%; height:100%; background-color:#eee; position:absolute; top:0; right:0; padding:20px; box-sizing:border-box; } .photo .side-front .image{ width:100%; height:250px; line-height:250px; overflow:hidden; } .photo .side-front .image img{ width:100%; } .photo .side-front .caption{ text-align:center; font-size:16px; line-height:50px; } .photo .side-back .desc{ color:#666; font-size:14px; line-height:1.5em; } /*The currently selected poster style*/ .photo_center{ /*---Implement vertical centering method one left:50%; top:50%; margin-left:-130px; margin-top:-160px; */ /*Implement vertical centering method two*/ top:0; bottom:0; left:0; right:0; margin:auto; z-index:999;//Let the currently selected poster not be covered by other posters} /*Responsible for flipping*/ .photo-wrap{ position:absolute; width:100%; height:100%; -moz-transform-style:perserve-3d; -webkit-transform-style:preserve-3d;/*Let the elements inside support the effect of 3d*/ transform-style:preserve-3d;/*Because of this sentence, the back of firefox cannot be displayed*/ -webkit-transition:all 1s; -moz-transition:all 1s; transition:all 1s; } .photo-wrap .side{ -moz-backface-visibility:hidden;//Hide when the screen is not facing the screen-webkit-backface-visibility:hidden; backface-visibility:hidden; } .photo-wrap .side-front{ -moz-transform:rotateY(0deg); -webkit-transform:rotateY(0deg); transform:rotateY(0deg); } .photo-wrap .side-back{ -moz-transform:rotateY(180deg); -webkit-transform:rotateY(180deg); transform:rotateY(180deg); } .photo-front .photo-wrap{ -moz-transform:rotateY(0deg); -webkit-transform:rotateY(0deg); transform:rotateY(0deg); } .photo-back .photo-wrap{ -moz-transform:rotateY(180deg); -webkit-transform:rotateY(180deg); transform:rotateY(180deg); } /*Control button style*/ .nav{ width:40%; height:30px; line-height:30px; position:absolute; left:30%; bottom:20px; z-index:999; /*background-color:#fff;*/ text-align:center; } /*Normal style*/ .nav .i{ width:30px; height:30px; display:inline-block; cursor:pointer; background-color:#aaa; text-align:center; border-radius:50%; -moz-transform:scale(.48); -webkit-transform:scale(.48); transform:scale(.48); -webkit-transition:all 1s; -moz-transition:all 1s; } .nav .i:after{ } /*Currently selected style*/ .nav .i_current{ -moz-transform:scale(1); -webkit-transform:scale(1); } .nav .i_current:after{ opacity:1; } /*Back{ -moz-transform:rotateY(-180deg); -webkit-transform:rotateY(-180deg); background-color:#555; } /*Style optimization, */ .photo{/*Definition below is to eliminate sudden flashes of images*/ left:50%; top:50%; margin:-160px 0 0 -130px; } .photo-wrap{ -moz-transform-origin:0% 50%; -webkit-transform-origin:0% 50%; } .photo-front .photo-wrap{ -moz-transform:translate(0px,0px) rotateY(0deg); -webkit-transform:translate(0px,0px) rotateY(0deg); } .photo-back .photo-wrap{ -moz-transform:translate(260px,0px) rotateY(180deg); -webkit-transform:translate(260px,0px) rotateY(180deg); }Here are some important parts of the style.
Settings in the case:-webkit-perspective:800px;
You can see the effect of setting this and then setting rotateY (45deg). If -webkit-transform is not set, the rotation effect will not be displayed. The rotation of the picture is just rotating on the plane. If it is set too small, the effect will be as follows:
div.photo is responsible for the translation and rotation of the picture, while div.photo-wrap is responsible for 3D flip (front and back switching). In order to enable the elements inside to support 3D effects, set -webkit-transform-style:preserve-3d for div.photo-wrap.
.photo-wrap .side style -webkit-backface-visibility: hidden; The purpose of this sentence is to hide when the element is not facing the screen.
In order to make the picture move and flip animation effect, set -webkit-transition for .photo-wrap: Let's see the explanation of transition below:
Navigation bar style
/*Normal style*/ .nav .i{ width:30px; height:30px; display:inline-block; cursor:pointer; background-color:#aaa; text-align:center; border-radius:50%; -moz-transform:scale(.48); -webkit-transform:scale(.48); transform:scale(.48); -webkit-transition:all 1s; -moz-transition:all 1s; } /*Currently selected style*/ .nav .i_current{ -moz-transform:scale(1); -webkit-transform:scale(1); } .nav .i_current:after{ opacity:1; } /*back style*/ .nav .i_back{ -moz-transform:rotateY(-180deg); -webkit-transform:rotateY(-180deg); background-color:#555; }Analysis diagram of navigation bar:
The buttons of the navigation bar are also divided into front and back. In order to distinguish the effects of the front and back, they are set to have different background colors, and at the same time, the flip effect is set to reduce the normal button - transform: scale(.48), and when the button is selected, scale(1). The reason for zooming in and out of the button is to know exactly whether the overall style will be destroyed when the current button is selected.
After all the basic styles are set, some optimizations will be made to the effect. In order to make the picture look slightly offset to the right like a door when switching front and back, you can add the following style:
/*Style optimization, */ .photo{/*Definition below is to eliminate sudden flashes of images*/ left:50%; top:50%; margin:-160px 0 0 -130px; } .photo-wrap{ -moz-transform-origin:0% 50%; -webkit-transform-origin:0% 50%; } .photo-front .photo-wrap{ -moz-transform:translate(0px,0px) rotateY(0deg); -webkit-transform:translate(0px,0px) rotateY(0deg); } .photo-back .photo-wrap{ -moz-transform:translate(260px,0px) rotateY(180deg); -webkit-transform:translate(260px,0px) rotateY(180deg); }Data section
The data is mainly written in data.js. A data array is defined in data.js to store information of 22 pictures. The output structure of data array is as follows:
Each object stored in data includes three attributes: caption, desc, and img. The contents of each object stored in data are output as follows. The data part is mainly used to replace strings in templates.
The content of data.js is as follows:
var data = [];var dataStr = '1. Photo 1<br>/<br>/ Green Vegetables<br>/<br>/<br>/2. Photo 2<br>/<br>/ Photo 2<br>/<br>/<br>/3. Photo 3<br>/<br>/<br>/<br>/4. Photo 4<br>/<br>/<br>/<br>/4. Photo 4<br>/<br>/<br>/5. Photo 5<br>/<br>/<br>/<br>/<br>/6. A super cute little bear toy<br>/<br>/ A super cute little bear toy<br>/<br>/ >/<br>/<br>/7, Photo 7<br>/<br>/<br>/<br>/8, Photo 8<br>/<br>/<br>/9, Photo 9<br>/<br>/<br>/<br>/9, Photo 9<br>/<br>/<br>/<br>/10, Photo 10<br>/<br>/<br>/11, Photo 11<br>/<br>/<br>/<br>/12, Photo 12<br>/<br>/<br>/ 12<br>/<br>/<br>/13, Photo 13<br>/<br>/<br>/<br>/14, Photo 14<br>/<br>/<br>/14, Photo 14<br>/<br>/<br>/15, Photo 15<br>/<br>/<br>/<br>/15, Photo 15<br>/<br>/<br>/<br>/16, Photo 16<br>/<br>/<br>/<br>/17, Photo 17<br>/<br>/<br>/<br>/17, Photo 17<br>/<br>/<br>/<br>/17, Photo 17<br>/<br>/<br>/<br>/17, Photo 17<br>/<br>/<br>/<br>/17, Photo 17<br>/<br>/<br>/<br>/18, Photo 18<br>/<br>/Photo 18<br>/<br>/19, Photo 19<br>/<br>/<br>/Photo 19<br>/<br>/20, Photo 20<br>/<br>/<br>/Photo 20<br>/<br>/21, Photo 21<br>/<br>/<br>/<br>/<br>/22, Photo 22<br>/<br>/';//The following code is to split the content in dataStr into the data array var d = dataStr.split('<br><br><br>');for(var i = 0;i < d.length; i++) { var c = d[i].split('<br><br>'); data.push({ img:'img'+(i+1)+'.jpg', caption:c[0].split(',')[1], desc:c[1] });}VCD decomposition-Controller control
•Output all poster content (view template + data)
•Position allocation control (central position, both sides position)
•Control bar output & control (switch, flip)
Output all posters, iterate through the data array, and fill the content into the template.
//4. Output all posters var data = data; function addPhotos(){ var template = $('#wrap').html(); var html = []; var nav = []; for(s in data) { var _html = template.replace('{{index}}',s) .replace('{{img}}',data[s].img) .replace('{{caption}}',data[s].caption) .replace('{{desc}}',data[s].desc); html.push(_html); // Each poster has a corresponding button nav.push('<span id="nav_'+s+'" onclick="turn(this)" > </span>'); } //Write back after traversal html.push('<div>'+nav.join('')+'</div>'); $('#wrap').html(html.join('')); rsort(random([0,data.length])); }The poster sorting, the analysis diagram is as follows:
When sorting posters for left and right partitions, first analyze the position of posters for left and right partitions as follows:
Use random numbers to generate the position left and top values of the current poster
//Create a random value, supporting the value range.random([min,max]); function random(range){ var max = Math.max(range[0],range[1]); var min = Math.min(range[0],range[1]); var diff = max-min; var number = Math.ceil(Math.random()*diff + min); return number; }//6. Calculate the range of left and right partitions {left:{x:[min,max],y[min,max]},right{x:[min,max],y:[min,max] }} function range() { var ran = { left:{ x:[],y:[] }, right:{ x:[],y:[] } }; var wrap = { w:$('#wrap').width(), //w:600, h:$('#wrap').height() } var photo = { w:$('.photo')[0].clientWidth, h:$('.photo')[0].clientHeight } ran.left.x = [0 - photo.w,wrap.w/2 - photo.w/2]; ran.left.y = [0 - photo.h,wrap.h]; ran.right.x = [wrap.w/2 + photo.w/2,wrap.w + photo.w]; ran.right.y = ran.left.y; return ran; }Then sort the posters
//5.Sorting poster function rsort(n) { var _photo = $('.photo'); var photos = []; for(var i = 0;i < _photo.length;i++) { _photo[i].className = _photo[i].className.replace(//s*photo_center/s*/,''); _photo[i].className = _photo[i].className.replace(//s*photo-front/s*/,''); _photo[i].className = _photo[i].className.replace(//s*photo-front/s*/,''); _photo[i].className = _photo[i].className = _photo[i].className.replace(//s*photo-back/s*/,''); //Because both photo-front and photo-back are replaced above, _photo[i].className += 'photo-front'; _photo[i].style.left = ''; _photo[i].style.top = ''; _photo[i].style['-moz-transform'] =_photo[i].style['transform'] = _photo[i].style['-webkit-transform'] = 'rotate(0deg) scale(1.3)'; photos.push(_photo[i]); } //var photo_center = $('#photo_'+n)[0]; var photo_center = document.getElementById('photo_'+n); var newClass = photo_center.className + ' photo_center'; //console.log(photo_center.attr('class')); photo_center = photos.splice(n,1)[0]; //photo_center.className = newClass; $('#photo_'+n).attr('class',newClass); //Divide the remaining poster into two parts var photos_left = photos.splice(0,Math.ceil(photos.length/2)); var photos_right = photos; var ranges = range(); //Left partition sorting for(s in photos_left) { var photo = photos_left[s]; photo.style.left = random(ranges.left.x) + 'px'; photo.style.top = random(ranges.left.y) + 'px'; photo.style['-moz-transform'] =photo.style['transform'] = photo.style['-webkit-transform'] = 'rotate('+random([-150,150])+'deg) scale(1)'; } //Right partition sort for(s in photos_right) { var photo = photos_right[s]; photo.style.left = random(ranges.right.x) + 'px'; photo.style.top = random(ranges.right.y) + 'px'; photo.style['-moz-transform'] = photo.style['transform'] = photo.style['-webkit-transform'] = photo.style['-webkit-transform'] = photo.style['-webkit-transform'] = 'rotate('+random([-100,100])+'deg) scale(1)'; } //Control button processing var navs = $('.i'); for(var i = 0;i<navs.length;i++) { navs[i].className = navs[i].className.replace(//s*i_current/s*/,''); navs[i].className = navs[i].className.replace(//s*i_back/s*/,''); } //Add i_current style $('#nav_'+n)[0].className += ' i_current'; }The switching effect of the front and back side of the poster and the switching effect of the control button:
function turn(elem) { var cls = elem.className; var n = elem.id.split('_')[1]; if(!(/photo_center/.test(cls))) { rsort(n); } //The className is changed after the execution of the if statement above, because I don't want this//There is always a lack of photo_center class var cs = $('#photo_'+n)[0]; cls = cs.className; if(/photo-front/.test(cls)) { cls = cls.replace(/photo-front/,'photo-back'); $('#nav_'+n)[0].className += ' i_back'; }else { cls = cls.replace(/photo-back/,'photo-front') $('#nav_'+n)[0].className = $('#nav_'+n)[0].className.replace(//s*i_back/s*/,''); } cs.className = cls; }You can understand which poster is the currently displayed poster based on n in rsort(n), and you can also know which button is the currently selected button.
The above is the corresponding effect analysis.
Summarize:
Ideas and methods for analyzing cases:
•Module analysis method
•VCD analysis method
Some new CSS effects
•3D view position settings & 3D sub-elements support
•Hide when flipped invisible
•Use CSS rotation (Y-axis) and displacement
•CSS switching animation
Front-end scripting skills
• Simple template function for string replacement
• Obtain some random numbers according to the range
• Use scripts to switch the element's className and specific style attributes
During the implementation process, a problem I encountered was that when flipping the image, the reverse side cannot be hidden in firefox. That is to say, there is a problem with the following code, and it has been checked for a long time.
.photo-wrap .side{ -moz-backface-visibility:hidden; -webkit-backface-visibility:hidden; backface-visibility:hidden;}It turns out to be: I missed the transform-style:preserve-3d . So when browser compatibility, remember to write styles without prefix
.photo-wrap{ position:absolute; width:100%; height:100%; -moz-transform-style:perserve-3d; -webkit-transform-style:preserve-3d;/*Let the elements inside support the effect of 3d*/ <span style="color:#cc0000;">transform-style:preserve-3d;/*Because of this sentence, the back of firefox cannot be displayed*/</span> -webkit-transition:all 1s; -moz-transition:all 1s; transition:all 1s; }Finally, the complete js code is attached:
<script type="text/javascript"> // generate a random value randomly, supporting the value range.random([min,max]); function random(range){ var max = Math.max(range[0],range[1]); var min = Math.min(range[0],range[1]); var diff = max-min; var number = Math.ceil(Math.random()*diff + min); return number; } //4. Output all posters var data = data; function addPhotos(){ var template = $('#wrap').html(); var html = []; var nav = []; for(s in data) { var _html = template.replace('{{index}}',s) .replace('{{img}}',data[s].img) .replace('{{caption}}',data[s].caption) .replace('{{desc}}',data[s].desc); html.push(_html); // Each poster has a corresponding button nav.push('<span id="nav_'+s+'" onclick="turn(this)" > </span>'); } html.push('<div>'+nav.join('')+'</div>'); $('#wrap').html(html.join('')); rsort(random([0,data.length])); } addPhotos() //6. Calculate the range of left and right partitions {left:{x:[min,max],y[min,max]},right{x:[min,max],y:[min,max] }} function range() { var ran = { left:{ x:[],y:[] }, right:{ x:[],y:[] } }; var wrap = { w:$('#wrap').width(), //w:600, h:$('#wrap').height() } var photo = { w:$('.photo')[0].clientWidth, h:$('.photo')[0].clientHeight } ran.left.x = [0 - photo.w,wrap.w/2 - photo.w/2]; ran.left.y = [0 - photo.h,wrap.h]; ran.right.x = [wrap.w/2 + photo.w/2,wrap.w + photo.w]; ran.right.y = ran.left.y; return ran; } //5. Sort poster function rsort(n) { var _photo = $('.photo'); var photos = []; for(var i = 0;i < _photo.length;i++) { _photo[i].className = _photo[i].className.replace(//s*photo_center/s*/,''); _photo[i].className = _photo[i].className.replace(//s*photo-front/s*/,''); _photo[i].className = _photo[i].className.replace(//s*photo-back/s*/,''); _photo[i].className = _photo[i].className.replace(//s*photo-back/s*/,''); //Because the above has replaced both photo-front and photo-back, _photo[i].className += ' photo-front'; _photo[i].style.left = ''; _photo[i].style.top = ''; _photo[i].style['-moz-transform'] =_photo[i].style['transform'] = _photo[i].style['-webkit-transform'] = 'rotate(0deg) scale(1.3)'; photos.push(_photo[i]); } //var photo_center = $('#photo_'+n)[0]; var photo_center = document.getElementById('photo_'+n); var newClass = photo_center.className + ' photo_center'; //console.log(photo_center.attr('class')); photo_center = photos.splice(n,1)[0]; //photo_center.className = newClass; $('#photo_'+n).attr('class',newClass); //dividing the remaining poster into two parts var photos_left = photos.splice(0,Math.ceil(photos.length/2)); var photos_right = photos; var ranges = range(); //Left partition sorting for(s in photos_left) { var photo = photos_left[s]; photo.style.left = random(ranges.left.x) + 'px'; photo.style.top = random(ranges.left.y) + 'px'; photo.style['-moz-transform'] = photo.style['transform'] = photo.style['-webkit-transform'] = 'rotate('+random([-150,150])+'deg) scale(1)'; } //Right partition sorting for(s in photos_right) { var photo = photos_right[s]; photo.style.left = random(ranges.right.x) + 'px'; photo.style.top = random(ranges.right.y) + 'px'; photo.style['-moz-transform'] = photo.style['transform'] = photo.style['-webkit-transform'] = 'rotate('+random([-100,100])+'deg) scale(1)'; } //Control button processing var navs = $('.i'); for(var i = 0;i<navs.length;i++) { navs[i].className = navs[i].className.replace(//s*i_current/s*/,''); navs[i].className = navs[i].className.replace(//s*i_back/s*/,''); } //Add i_current style $('#nav_'+n)[0].className += ' i_current'; } function turn(elem) { var cls = elem.className; var n = elem.id.split('_')[1]; if(!(/photo_center/.test(cls))) { rsort(n); } //The className is changed after the execution of the if statement above, because I don't want this//The photo_center class var cs = $('#photo_'+n)[0]; cls = cs.className; if(/photo-front/.test(cls)) { cls = cls.replace(/photo-front/,'photo-back'); $('#nav_'+n)[0].className += ' i_back'; }else { cls = cls.replace(/photo-back/,'photo-front') $('#nav_'+n)[0].className = $('#nav_'+n)[0].className.replace(//s*i_back/s*/,''); } cs.className = cls; } </script>The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.