Circular Display Pictures (Picture-in-Picture Effect) CANVAS 2.0 Edition

Keywords: Mobile

Circular Display Pictures (Picture-in-Picture Effect) CANVAS 2.0 Edition
Previously designed version has some problems in testing. PC-side testing is not a problem, but when accessed on mobile phones, flash screen appears when the screen is cut (the original big picture does not appear, the previous small picture suddenly becomes bigger, flashes past, and then shows the normal big picture). To sum up the reasons, it should still be slow loading on the mobile side.
This edition has been optimized. When the first screen is loaded with three pictures, the next screen is pre-loaded. When the next screen is loaded, only one picture of the next screen is pre-loaded. After testing, the problem of flash screen will not arise.
In addition, the operation button is hidden at the end, and a callback method is added to determine whether callback is needed based on the parameters at the time of invocation.

Contains the JS file CanvasCycleShowImg.2.0.js:
/*
JS Constantly insert two pictures into CANVAS (src, width and height of the pictures, position of the pictures, etc.) to display pictures in a circular way (picture-in-picture effect)
author Yu Jun
2017-07-06
*/
function CanvasCycleShowImg(){
	//The actual size of the picture used
	this.imgMsg = {w:640,h:1138};
	//The position, width and height information settings of all pictures (set according to the actual size of the picture). The values in inX, inY, inW and inH represent the information of the previous picture in this picture (when the picture is displayed in its final state).
	this.imgList = [
					{
						imgsrc:'1.jpg',
						inX:'',
						inY:'',
						inW:'',
						inH:''
					},
					{
						imgsrc:'2.jpg',
						inX:470,
						inY:50,
						inW:118,
						inH:210
					},
					{
						imgsrc:'3.jpg',
						inX:86,
						inY:561,
						inW:195,
						inH:346
					},
					{
						imgsrc:'4.jpg',
						inX:266,
						inY:472,
						inW:118,
						inH:210
					},
				];
	//How many steps to complete the change from start to end
	this.step  = 300;
	//Timer interval (in milliseconds)
	this.timerTime = 10;
	
	//Add Configuration Styles and Label Elements
	//The mobile side adds this style setting: HTML {min-width: 320px; max-width: 640px; margin: 0 auto;}\
	this.headStyle = '<style>\
						*{ margin:0px; padding:0px; box-sizing:border-box; -webkit-tap-highlight-color:rgba(0,0,0,0);}\n\
						html{ min-width:320px; max-width:640px; margin:0 auto;}\n\
						html , body{ display:block; width:100%; height:100%;}\n\
						#btn{ width:50px; height:50px; line-height:50px; text-align:center; color:#fff; border-radius:50%; background-color:#f00; cursor:pointer; position:absolute; left:50%; margin-left:-25px; bottom:20px;}\
					</style>';
	this.showImgEle = '<div id="showImg" style=" width:100%; height:100%; overflow:hidden; position:relative;">\
						<canvas id="showImgCanvas" style=" width:100%; position:absolute; left:0; top:0;" />\
					</div>';
	this.showImgBtn = '<div id="btn"></div>';
}

CanvasCycleShowImg.prototype.init = function (callback){
	//Whether there is a callback at the end depends on the parameters.
	var if_callback = false;
	if(arguments[0]){
		if_callback = true;
	}
	
	var headStyle = this.headStyle;
	$('head').append(headStyle);
	var showImgEle = this.showImgEle;
	$('body').prepend(showImgEle);
	var showImgBtn = this.showImgBtn;
	$('#showImg').after(showImgBtn);

	var imgMsg  = this.imgMsg;
	var imgList = this.imgList;
	//Starting of array subscripts for all picture declarations
	var start = 0;
	//All image declarations end with array subscripts
	var end   = imgList.length - 2;
	var step  = this.step;
	//Step 1
	var stepNum   = 1;
	var timerTime = this.timerTime;
	//When the page interacts, the user always sees only two pictures. The picture below is big and the picture above is small. The following method sets the information of the start, the position and size of the final display status of the two pictures.
	function getPoint(start){
		/*
		start     ===> Picture 1 (the picture shown above)
		start + 1 ===> Figure 2 (the one shown below)
		The following definitions of x, y, w, H = > are set in the above array (imgList), which corresponds to the actual size of the picture, indicating the position and width shown in the first picture in the second picture.
		*/
		x = imgList[start + 1].inX;
		y = imgList[start + 1].inY;
		w = imgList[start + 1].inW;
		h = imgList[start + 1].inH;
		//The starting state (enlargement) ratio of the second picture, that is, the ratio of the starting state to the final state of the first picture: the actual width of the picture / the actual reduced width of the picture
		var fdbl = imgMsg.w / w;
		//The ratio of the final state (reduction) of the first picture, that is, the ratio of the final state to the initial state of the first picture: the actual width of the reduced picture / the actual width of the picture
		var sxbl = w / imgMsg.w;
		
		/******Location Information and Width and Height Settings for the Final State of Figure 1****/
		var minToX = x;
		var minToY = y;
		var minToW = w;
		var minToH = h;
		/******Location Information and Width and Height Settings for the Starting State of Figure 2****/
		var maxStartX = minToX  * fdbl * -1;
		var maxStartY = minToY  * fdbl * -1;
		var maxStartW = imgMsg.w  * fdbl;
		var maxStartH = imgMsg.h  * fdbl;
		var point = {
				minStartX : 0,
				minStartY : 0,
				minStartW : imgMsg.w,
				minStartH : imgMsg.h,
				
				minToX    : minToX,
				minToY    : minToY,
				minToW    : minToW,
				minToH    : minToH,
				
				minStepX  : minToX / step,
				minStepY  : minToY / step,
				minStepW  : (imgMsg.w - minToW) / step,
				minStepH  : (imgMsg.h - minToH) / step,
				
				
				maxStartX : maxStartX,
				maxStartY : maxStartY,
				maxStartW : maxStartW,
				maxStartH : maxStartH,
				
				maxToX    : 0,
				maxToY    : 0,
				maxToW    : imgMsg.w,
				maxToH    : imgMsg.h,
				
				maxStepX  : maxStartX / step,
				maxStepY  : maxStartY / step,
				maxStepW  : (maxStartW - imgMsg.w) / step,
				maxStepH  : (maxStartH - imgMsg.h) / step,
			};
		console.log(point);
		return point;
	}
	//Drawing
	var showImgCanvas = document.getElementById("showImgCanvas");
	var showImgCanvas_2d = showImgCanvas.getContext("2d");
	showImgCanvas.width  = imgMsg.w;
	showImgCanvas.height = imgMsg.h;
	var img1  = new Image();
	var img2  = new Image();
	var img3  = new Image();
	function drawImg(w1,h1,x1,y1,w2,h2,x2,y2){
		showImgCanvas_2d.clearRect(0,0,imgMsg.w,imgMsg.h);
		showImgCanvas_2d.drawImage(img2,x2,y2,w2,h2);
		showImgCanvas_2d.drawImage(img1,x1,y1,w1,h1);
	}
	//Configure the initial picture display status
	function setImgMsg(start){
		var ImgMsg = getPoint(start);
		if(start > 0){//The second screen and later, the current screen has been fully loaded on the previous screen, just pre-loaded a picture of the next screen.
			img1 = img2;
			img2 = img3;
			drawImg(ImgMsg.minStartW , ImgMsg.minStartH , ImgMsg.minStartX , ImgMsg.minStartY , ImgMsg.maxStartW , ImgMsg.maxStartH , ImgMsg.maxStartX , ImgMsg.maxStartY);
			var byimg = new Image();
			if(start < end){//No need to preload the next screen when the last screen
				byimg.src = imgList[start + 2].imgsrc;
				byimg.onload = function(){
					img3 = byimg;
					console.log(img1,img2,img3);
				}
			}
		}else{//Load the first three pictures on the first screen (two pictures on the current screen and one picture on the next screen)
			img2.src = imgList[start + 1].imgsrc;
			img2.onload = function(){
				drawImg(ImgMsg.minStartW , ImgMsg.minStartH , ImgMsg.minStartX , ImgMsg.minStartY , ImgMsg.maxStartW , ImgMsg.maxStartH , ImgMsg.maxStartX , ImgMsg.maxStartY);
				img1.src = imgList[start].imgsrc;
				img1.onload = function(){
					img3.src = imgList[start + 2].imgsrc;
					img3.onload = function(){
						console.log(img1,img2,img3);
					}
				}
			}
		}
		return ImgMsg;
	}

	var pointMsg = setImgMsg(start);
	var imgTimer;
	document.getElementById('btn').addEventListener('touchstart',touchStart,false);
	document.getElementById('btn').addEventListener('mousedown',touchStart,false);
	function touchStart(e){
		e.preventDefault();
		clearInterval(imgTimer);
		imgTimer = setInterval(showDh,timerTime);
	}
	document.getElementById('btn').addEventListener('touchend',touchEnd,false);
	document.getElementById('btn').addEventListener('mouseup',touchEnd,false);
	function touchEnd(e){
		clearInterval(imgTimer);
	}
	function showDh(){
		if(stepNum > step){
			if(start >= end){
				$('#btn').fadeOut('fast');
				clearInterval(imgTimer);
				//End callback method
				if(if_callback){
					callback();
				}
				return;
			}else{
				start++;
				stepNum = 1;
				pointMsg = setImgMsg(start);
			}
			return;
		}
		//console.log(stepNum , start , end);
																		
		drawImg(pointMsg.minStartW - stepNum * pointMsg.minStepW , pointMsg.minStartH - stepNum * pointMsg.minStepH , pointMsg.minStartX + stepNum * pointMsg.minStepX , pointMsg.minStartY + stepNum * pointMsg.minStepY , pointMsg.maxStartW - stepNum * pointMsg.maxStepW , pointMsg.maxStartH - stepNum * pointMsg.maxStepH , pointMsg.maxStartX - stepNum * pointMsg.maxStepX , pointMsg.maxStartY - stepNum * pointMsg.maxStepY);
													
		stepNum ++;
	}
}

Contains the JS file CanvasCycleShowImg.2.0-min.js:
/*
JS Constantly insert two pictures into CANVAS (src, width and height of the pictures, position of the pictures, etc.) to display pictures in a circular way (picture-in-picture effect)
author Yu Jun
2017-07-06
*/
function CanvasCycleShowImg(){this.imgMsg={w:640,h:1138};this.imgList=[{imgsrc:'1.jpg',inX:'',inY:'',inW:'',inH:''},{imgsrc:'2.jpg',inX:470,inY:50,inW:118,inH:210},{imgsrc:'3.jpg',inX:86,inY:561,inW:195,inH:346},{imgsrc:'4.jpg',inX:266,inY:472,inW:118,inH:210},];this.step=300;this.timerTime=10;this.headStyle='<style>\
      *{ margin:0px; padding:0px; box-sizing:border-box; -webkit-tap-highlight-color:rgba(0,0,0,0);}\n\
      html{ min-width:320px; max-width:640px; margin:0 auto;}\n\
      html , body{ display:block; width:100%; height:100%;}\n\
      #btn{ width:50px; height:50px; line-height:50px; text-align:center; color:#fff; border-radius:50%; background-color:#f00; cursor:pointer; position:absolute; left:50%; margin-left:-25px; bottom:20px;}\
     </style>';this.showImgEle='<div id="showImg" style=" width:100%; height:100%; overflow:hidden; position:relative;">\
      <canvas id="showImgCanvas" style=" width:100%; position:absolute; left:0; top:0;" />\
     </div>';this.showImgBtn='<div id="btn"></div>';}
CanvasCycleShowImg.prototype.init=function(callback){var if_callback=false;if(arguments[0]){if_callback=true;}
var headStyle=this.headStyle;$('head').append(headStyle);var showImgEle=this.showImgEle;$('body').prepend(showImgEle);var showImgBtn=this.showImgBtn;$('#showImg').after(showImgBtn);var imgMsg=this.imgMsg;var imgList=this.imgList;var start=0;var end=imgList.length-2;var step=this.step;var stepNum=1;var timerTime=this.timerTime;function getPoint(start){x=imgList[start+1].inX;y=imgList[start+1].inY;w=imgList[start+1].inW;h=imgList[start+1].inH;var fdbl=imgMsg.w/w;var sxbl=w/imgMsg.w;var minToX=x;var minToY=y;var minToW=w;var minToH=h;var maxStartX=minToX*fdbl* -1;var maxStartY=minToY*fdbl* -1;var maxStartW=imgMsg.w*fdbl;var maxStartH=imgMsg.h*fdbl;var point={minStartX:0,minStartY:0,minStartW:imgMsg.w,minStartH:imgMsg.h,minToX:minToX,minToY:minToY,minToW:minToW,minToH:minToH,minStepX:minToX/step,minStepY:minToY/step,minStepW:(imgMsg.w-minToW)/step,minStepH:(imgMsg.h-minToH)/step,maxStartX:maxStartX,maxStartY:maxStartY,maxStartW:maxStartW,maxStartH:maxStartH,maxToX:0,maxToY:0,maxToW:imgMsg.w,maxToH:imgMsg.h,maxStepX:maxStartX/step,maxStepY:maxStartY/step,maxStepW:(maxStartW-imgMsg.w)/step,maxStepH:(maxStartH-imgMsg.h)/step,};console.log(point);return point;}
var showImgCanvas=document.getElementById("showImgCanvas");var showImgCanvas_2d=showImgCanvas.getContext("2d");showImgCanvas.width=imgMsg.w;showImgCanvas.height=imgMsg.h;var img1=new Image();var img2=new Image();var img3=new Image();function drawImg(w1,h1,x1,y1,w2,h2,x2,y2){showImgCanvas_2d.clearRect(0,0,imgMsg.w,imgMsg.h);showImgCanvas_2d.drawImage(img2,x2,y2,w2,h2);showImgCanvas_2d.drawImage(img1,x1,y1,w1,h1);}
function setImgMsg(start){var ImgMsg=getPoint(start);if(start>0){img1=img2;img2=img3;drawImg(ImgMsg.minStartW,ImgMsg.minStartH,ImgMsg.minStartX,ImgMsg.minStartY,ImgMsg.maxStartW,ImgMsg.maxStartH,ImgMsg.maxStartX,ImgMsg.maxStartY);var byimg=new Image();if(start<end){byimg.src=imgList[start+2].imgsrc;byimg.onload=function(){img3=byimg;console.log(img1,img2,img3);}}}else{img2.src=imgList[start+1].imgsrc;img2.onload=function(){drawImg(ImgMsg.minStartW,ImgMsg.minStartH,ImgMsg.minStartX,ImgMsg.minStartY,ImgMsg.maxStartW,ImgMsg.maxStartH,ImgMsg.maxStartX,ImgMsg.maxStartY);img1.src=imgList[start].imgsrc;img1.onload=function(){img3.src=imgList[start+2].imgsrc;img3.onload=function(){console.log(img1,img2,img3);}}}}
return ImgMsg;}
var pointMsg=setImgMsg(start);var imgTimer;document.getElementById('btn').addEventListener('touchstart',touchStart,false);document.getElementById('btn').addEventListener('mousedown',touchStart,false);function touchStart(e){e.preventDefault();clearInterval(imgTimer);imgTimer=setInterval(showDh,timerTime);}
document.getElementById('btn').addEventListener('touchend',touchEnd,false);document.getElementById('btn').addEventListener('mouseup',touchEnd,false);function touchEnd(e){clearInterval(imgTimer);}
function showDh(){if(stepNum>step){if(start>=end){$('#btn').fadeOut('fast');clearInterval(imgTimer);if(if_callback){callback();}
return;}else{start++;stepNum=1;pointMsg=setImgMsg(start);}
return;}
drawImg(pointMsg.minStartW-stepNum*pointMsg.minStepW,pointMsg.minStartH-stepNum*pointMsg.minStepH,pointMsg.minStartX+stepNum*pointMsg.minStepX,pointMsg.minStartY+stepNum*pointMsg.minStepY,pointMsg.maxStartW-stepNum*pointMsg.maxStepW,pointMsg.maxStartH-stepNum*pointMsg.maxStepH,pointMsg.maxStartX-stepNum*pointMsg.maxStepX,pointMsg.maxStartY-stepNum*pointMsg.maxStepY);stepNum++;}}

Contains the JS file CanvasCycleShowImg.2.0-jm.js:
/*
JS Constantly insert two pictures into CANVAS (src, width and height of the pictures, position of the pictures, etc.) to display pictures in a circular way (picture-in-picture effect)
author Yu Jun
2017-07-06
*/
eval(function(a,b,c,d,e,f){if(e=function(a){return(b>a?"":e(parseInt(a/b)))+((a%=b)>35?String.fromCharCode(a+29):a.toString(36))},!"".replace(/^/,String)){for(;c--;)f[e(c)]=d[c]||e(c);d=[function(a){return f[a]}],e=function(){return"\\w+"},c=1}for(;c--;)d[c]&&(a=a.replace(new RegExp("\\b"+e(c)+"\\b","g"),d[c]));return a}("b 1q(){a.6={w:1Z,h:1S};a.d=[{g:'1.Q',t:'',v:'',I:'',G:''},{g:'2.Q',t:1T,v:18,I:1A,G:1z},{g:'3.Q',t:2g,v:2f,I:22,G:2j},{g:'4.Q',t:2l,v:2e,I:1A,G:1z},];a.f=2a;a.15=10;a.T='<Y>*{ 19:1H; 29:1H; 1m-2b:1o-1m; -28-27-23-1a:24(0,0,0,0);}1r{ 25-p:26; 2k-p:2m; 19:0 2i;}1r , 1n{ 2h:2n; p:z%; F:z%;}#m{ p:1j; F:1j; 1Y-F:1j; 1R-21:20; 1a:#1U; 1o-1X:18%; 1V-1a:#1W; 2c:2t; 16:1p; 1l:18%; 19-1l:-2Q; 2O:2H;}</Y>';a.13='<12 1i=\"1s\"Y=\" p:z%; F:z%; 2J:2N; 16:2L;\">\\<2M 1i=\"s\"Y=\" p:z%; 16:1p; 1l:0; 2K:0;\"/>\\</12>';a.J='<12 1i=\"m\"></12>'}1q.2I.2S=b(1w){5 1d=D;r(2U[0]){1d=2T}5 T=a.T;$('2P').2R(T);5 13=a.13;$('1n').2G(13);5 J=a.J;$('#1s').2E(J);5 6=a.6;5 d=a.d;5 7=0;5 1c=d.2u-2;5 f=a.f;5 c=1;5 15=a.15;b 1v(7){x=d[7+1].t;y=d[7+1].v;w=d[7+1].I;h=d[7+1].G;5 E=6.w/w;5 2v=w/6.w;5 A=x;5 B=y;5 L=w;5 N=h;5 j=A*E*-1;5 q=B*E*-1;5 n=6.w*E;5 k=6.h*E;5 1h={X:0,Z:0,U:6.w,W:6.h,A:A,B:B,L:L,N:N,1E:A/f,1u:B/f,1C:(6.w-L)/f,1D:(6.h-N)/f,j:j,q:q,n:n,k:k,2o:0,2F:0,2s:6.w,2p:6.h,1Q:j/f,1P:q/f,1x:(n-6.w)/f,1I:(k-6.h)/f,};1f.1g(1h);11 1h}5 s=C.H(\"s\");5 M=s.2q(\"2d\");s.p=6.w;s.F=6.h;5 o=O P();5 i=O P();5 l=O P();b V(1y,1t,1G,1F,1M,1O,1K,1J){M.2r(0,0,6.w,6.h);M.1N(i,1K,1J,1M,1O);M.1N(o,1G,1F,1y,1t)}b 1k(7){5 9=1v(7);r(7>0){o=i;i=l;V(9.U,9.W,9.X,9.Z,9.n,9.k,9.j,9.q);5 R=O P();r(7<1c){R.K=d[7+2].g;R.S=b(){l=R;1f.1g(o,i,l)}}}1B{i.K=d[7+1].g;i.S=b(){V(9.U,9.W,9.X,9.Z,9.n,9.k,9.j,9.q);o.K=d[7].g;o.S=b(){l.K=d[7+2].g;l.S=b(){1f.1g(o,i,l)}}}}11 9}5 8=1k(7);5 u;C.H('m').14('2w',17,D);C.H('m').14('2x',17,D);b 17(e){e.2C();1e(u);u=2D(1L,15)}C.H('m').14('2B',1b,D);C.H('m').14('2A',1b,D);b 1b(e){1e(u)}b 1L(){r(c>f){r(7>=1c){$('#m').2y('2z');1e(u);r(1d){1w()}11}1B{7++;c=1;8=1k(7)}11}V(8.U-c*8.1C,8.W-c*8.1D,8.X+c*8.1E,8.Z+c*8.1u,8.n-c*8.1x,8.k-c*8.1I,8.j-c*8.1Q,8.q-c*8.1P);c++}}",62,181,"|||||var|imgMsg|start|pointMsg|ImgMsg|this|function|stepNum|imgList||step|imgsrc||img2|maxStartX|maxStartH|img3|btn|maxStartW|img1|width|maxStartY|if|showImgCanvas|inX|imgTimer|inY||||100|minToX|minToY|document|false|fdbl|height|inH|getElementById|inW|showImgBtn|src|minToW|showImgCanvas_2d|minToH|new|Image|jpg|byimg|onload|headStyle|minStartW|drawImg|minStartH|minStartX|style|minStartY||return|div|showImgEle|addEventListener|timerTime|position|touchStart|50|margin|color|touchEnd|end|if_callback|clearInterval|console|log|point|id|50px|setImgMsg|left|box|body|border|absolute|CanvasCycleShowImg|html|showImg|h1|minStepY|getPoint|callback|maxStepW|w1|210|118|else|minStepW|minStepH|minStepX|y1|x1|0px|maxStepH|y2|x2|showDh|w2|drawImage|h2|maxStepY|maxStepX|text|1138|470|fff|background|f00|radius|line|640|center|align|195|highlight|rgba|min|320px|tap|webkit|padding|300|sizing|cursor||472|561|86|display|auto|346|max|266|640px|block|maxToX|maxToH|getContext|clearRect|maxToW|pointer|length|sxbl|touchstart|mousedown|fadeOut|fast|mouseup|touchend|preventDefault|setInterval|after|maxToY|prepend|20px|prototype|overflow|top|relative|canvas|hidden|bottom|head|25px|append|init|true|arguments".split("|"),0,{}));

Instance:
var CanvasCycleShowImg = new CanvasCycleShowImg();

The following parameters are optional and default values are used without setting them
Canvas CycleShowImg.imgMsg = {w:640, h:1138}; // The actual size of the image used, if the image used is not some size, please reset it.
Canvas CycleShowImg. Step = 300; // How many steps complete the change from start to end state
Canvas CycleShowImg.timerTime = 10; //timer interval time (in milliseconds)
// The following is a general way to redefine the "press" button style and reset it
CanvasCycleShowImg.headStyle = '<style>\
*{ margin:0px; padding:0px; box-sizing:border-box; -webkit-tap-highlight-color:rgba(0,0,0,0);}\n\
html{ min-width:320px; max-width:640px; margin:0 auto;}\n\
html , body{ display:block; width:100%; height:100%;}\n\
#btn{ width:50px; height:50px; line-height:50px; text-align:center; color:#fff; border-radius:50%; background-color:#f00; cursor:pointer; position:absolute; left:50%; margin-left:-25px; bottom:20px;}\
</style>';

The following parameters must be reset. The imgList is all the pictures to be displayed on the page (the position and width of all pictures are set according to the actual size of the picture). The values in inX, inY, inW and inH represent the information of the previous picture in this picture (when the picture is finally displayed).
CanvasCycleShowImg.imgList = [
{
imgsrc:'test/1.jpg',
inX:'',
inY:'',
inW:'',
inH:''
},
{
imgsrc:'test/2.jpg',
inX:470,
inY:50,
inW:118,
inH:210
},
{
imgsrc:'test/3.jpg',
inX:86,
inY:561,
inW:195,
inH:346
},
{
imgsrc:'test/4.jpg',
inX:266,
inY:472,
inW:118,
inH:210
},
];
// Perform the following methods to implement functionality
// No callback is required for the last screen
CanvasCycleShowImg.init();
// Callback is required for the last screen
//CanvasCycleShowImg.init(theEnd);
function theEnd(){
setTimeout(function(){
alert('has reached the last screen ~');
},1000);
}

Posted by Gayner on Sat, 15 Jun 2019 16:54:45 -0700