اسلایدر زیبا و کاربردی به اسم Zoom Slider
ﺯﻣﺎﻥ ﻣﻄﺎﻟﻌﻪ: 2 دقیقه

اسلایدر زیبا و کاربردی به اسم Zoom Slider

این پلاگین یک اسلاید ساده برای محتوا مورد نیازتونه که در عین حال که سادست ، بسیار زیبا و کاربردی هم هست که قابلیت زوم به عمق محتوای مورد نظرتون رو داره که از پیش توسط خودتون تعیین میشه . 

zoom silider

دانلود فایل | دمو

همونطور که گفتم امروز قراره یک اسلاید با قابلیت زوم رو بهتون معرفی کنیم که توسط سایت Blueprint ​ارائه شده امیدوارم لذت ببرید و مورد استفاده اتون قرار بگیره .  هر اسلاید از یک منطقه زوم از پیش تعریف شده استفاده میکنه که با استفاده از اون یه محتوای از پیش تعریف شده کل صفحه رو به خودش اختصاص میده . هنگامی که رو نماد زوم کلیک کنید ، بصورتی به محتوایی جدید انتقال پیدا میکنه که بنظر میرسه ، یک صفحه جدید رو دریافت میکنید و این توهم رو ایجاد میکنه که دارین به یه چیزی نزدیک میشین . هنگامی که کل صفحه پوشش داده شد ما میتونیم از اون اسلاید جزئیات بیشتری رو ببینیم . 

منو ناوبری که در زیر اسلاید قرار داره باعث ایجاد یک افکت زیبا برای تغیییر اسلاید ها میشه که به راحتی میتونید ازش برای تغییر اسلاید استفاده کنید . برای تغییر اسلاید ها از css transitions و dymanic.js استفاده شده است . Dymanic.js یک کتابخانه جاوااسکریپت که از اون برای حرکت دادن عناصر اسلاید استفاده میشه . 

هشدار : این اسلاید برای مرورگر های مدرن آماده شده است پس در استفاده از اون دقت کنید .

در زیر کد های html , css , javascript رو میاریم که می تونید در اینجا ازش استفاده کنید . 

کد های HTML

<!-- Main container -->
<div class="container">
	<!-- Blueprint header -->
	<header class="bp-header cf">
		<!-- Page title etc. -->
	</header>
	<!-- Grid -->
	<section class="slider">
		<div class="slide slide--current" data-content="content-1">
			<div class="slide__mover">
				<div class="zoomer flex-center">
					<img class="zoomer__image" src="images/iphone.png" alt="iPhone" />
					<div class="preview">
						<img src="images/iphone-content-preview.png" alt="iPhone app preview" />
						<div class="zoomer__area zoomer__area--size-2"></div>
					</div>
				</div>
			</div>
			<h2 class="slide__title"><span>The Classy</span> iPhone 6</h2>
		</div>
		<div class="slide" data-content="content-2">
			<!-- ... -->
		</div>
		<!-- ... -->
		<nav class="slider__nav">
			<button class="button button--nav-prev">
				<i class="icon icon--arrow-left"></i>
				<span class="text-hidden">Previous product</span>
			</button>
			<button class="button button--zoom">
				<i class="icon icon--zoom"></i>
				<span class="text-hidden">View details</span>
			</button>
			<button class="button button--nav-next">
				<i class="icon icon--arrow-right"></i>
				<span class="text-hidden">Next product</span>
			</button>
		</nav>
	</section>
	<!-- /slider-->
	<!-- content -->
	<section class="content">
		<div class="content__item" id="content-1">
			<img class="content__item-img rounded-right" src="images/iphone-content.png" alt="Apple Watch Content" />
			<div class="content__item-inner">
				<h2>The iPhone 6</h2>
				<h3>Incredible performance for powerful apps</h3>
				<p>...</p>
			</div>
		</div>
		<div class="content__item" id="content-2">
			<!-- ... -->
		</div>
		<!-- ... -->
		<button class="button button--close">
			<i class="icon icon--circle-cross"></i>
			<span class="text-hidden">Close content</span>
		</button>
	</section>
	<!-- /content -->
</div>
<script src="js/classie.js"></script>
<script src="js/dynamics.min.js"></script>
<script src="js/main.js"></script>

کدهای CSS

/* Helper classes */
html,
body {
	overflow: hidden;
	height: 100%;
}

.container {
	position: relative;
	overflow: hidden;
	overflow-y: scroll;
	width: 100%;
	height: 100%;
	-webkit-overflow-scrolling: touch;
}

.noscroll .container {
	overflow-y: hidden;
}

.slider {
	position: relative;
	z-index: 200;
	width: 100%;
	margin: 0 auto;
	padding: 0 0 7em;
	text-align: center;
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
	-webkit-touch-callout: none;
	-khtml-user-select: none;
}

.slide {
	position: absolute;
	top: 0;
	visibility: hidden;
	width: 100%;
	opacity: 0;
}

.slide--current {
	position: relative;
	z-index: 100;
	visibility: visible;
	opacity: 1;
}

.slide__mover {
	position: relative;
	z-index: 100;
}

.slide__title {
	font-size: 1.75em;
	font-weight: normal;
	margin: 0 auto;
	padding: 1em 0 0 0;
}

.slide__title span {
	font-size: 55%;
	font-weight: bold;
	display: block;
	letter-spacing: 2px;
	text-transform: uppercase;
	color: #35303d;
}

.slider__nav {
	position: absolute;
	bottom: 2em;
	width: 100%;
	text-align: center;
}

.button {
	font-size: 1.31em;
	position: relative;
	display: inline-block;
	overflow: hidden;
	margin: 0 25px;
	padding: 0;
	cursor: pointer;
	color: #5c5edc;
	border: none;
	background: none;
}

.button:focus {
	outline: none;
}

.button:hover {
	color: #fff;
}

.text-hidden {
	position: absolute;
	top: 200%;
}

.button--close {
	font-size: 1.55em;
	position: absolute;
	top: 30px;
	right: 30px;
	margin: 0;
	opacity: 0;
	color: #50505a;
	-webkit-transition: opacity 0.3s;
	transition: opacity 0.3s;
}

.content--open .button--close {
	opacity: 1;
}

/* Zoomer */
.zoomer {
	position: relative;
	height: 360px; /* this is needed for IE10 so that vertical flexbox centering works */
}

.flex-center {
	display: -webkit-flex;
	display: -ms-flexbox;
	display: flex;
	-webkit-align-items: center;
	-ms-flex-align: center;
	align-items: center;
	-webkit-justify-content: center;
	-ms-flex-pack: center;
	justify-content: center;
}

.zoomer__image {
	display: block;
	margin: 0;
	-webkit-flex: none;
	-ms-flex: none;
	flex: none;
}

.zoomer__area,
.preview {
	position: absolute;
	top: 50%;
	left: 50%;
	-webkit-transform: translate3d(-50%,-50%,0);
	transform: translate3d(-50%,-50%,0);
}

.zoomer__area:focus {
	outline: none;
}

.zoomer__area--size-1 {
	/* Apple Watch */
	width: 96px;
	height: 118px;
}

.zoomer__area--size-2 {
	/* iPhone */
	width: 112px;
	height: 198px;
}

.zoomer__area--size-3 {
	/* MacBook */
	width: 315px;
	height: 200px;
}

.zoomer__area--size-4 {
	/* iPad */
	width: 150px;
	height: 200px;
}

.zoomer__area--size-5 {
	/* iMac */
	width: 315px;
	height: 189px;
}

.preview {
	overflow: hidden;
	background: #18191b;
}

.preview img {
	display: block;
	border-radius: inherit;
	-webkit-transform: translate3d(0,0,0);
	transform: translate3d(0,0,0);
}

.zoomer--active .preview img {
	-webkit-transform: translate3d(100%,0,0);
	transform: translate3d(100%,0,0);
}

.rounded {
	border-radius: 15px;
}

.rounded-right {
	border-radius: 0 15px 15px 0;
}

.preview__content {
	position: absolute;
	top: 0;
	left: 100%;
	width: 100%;
	height: 100%;
	border-radius: inherit;
}
/* Content */
.content {
	position: fixed;
	z-index: 1000;
	top: 0;
	left: -100%;
	overflow: hidden;
	overflow-y: scroll;
	width: 100%;
	height: 100vh;
	background: #18191b;
	-webkit-overflow-scrolling: touch;
}

.content--open {
	left: 0;
}

.content__item {
	position: absolute;
	top: 0;
	display: -webkit-flex;
	display: -ms-flexbox;
	display: flex;
	overflow: hidden;
	height: 0;
	min-height: 100%;
	margin: 0 auto;
	padding: 2em 0;
	pointer-events: none;
	opacity: 0;
	color: #fff;
	-webkit-align-items: center;
	-ms-flex-align: center;
	align-items: center;
}

.content__item--current {
	pointer-events: auto;
	opacity: 1;
}

.content__item--reset {
	height: auto;
}

.content h2 {
	font-size: 3.5em;
	font-weight: normal;
	margin: 0;
}

.content h3 {
	font-size: 1.95em;
	font-weight: normal;
	margin: 0.25em 0 0.5em;
	color: #685884;
}

.content p {
	font-size: 1.25em;
	line-height: 1.5;
}

.content__item-img {
	display: block;
	max-width: 40vw;
	max-height: 80vh;
	-webkit-transform: translate3d(-120%,0,0);
	transform: translate3d(-120%,0,0);
	-webkit-flex: none;
	-ms-flex: none;
	flex: none;
}

.content__item--current .content__item-img {
	-webkit-transform: translate3d(-10px,0,0);
	transform: translate3d(-10px,0,0);
}

.content__item-inner {
	padding: 0 10vw 0;
	opacity: 0;
	-webkit-transform: translate3d(0,50px,0);
	transform: translate3d(0,50px,0);
}

.content__item--current .content__item-inner {
	opacity: 1;
	-webkit-transform: translate3d(0,0,0);
	transform: translate3d(0,0,0);
}


/**************************/
/* All synced transitions */
/**************************/

.zoomer {
	-webkit-transition: -webkit-transform 0.5s;
	transition: transform 0.5s;
	-webkit-transition-timing-function: cubic-bezier(0.7,0,0.3,1);
	transition-timing-function: cubic-bezier(0.7,0,0.3,1);
}

.zoomer.zoomer--notrans {
	-webkit-transition: none;
	transition: none;
}

.zoomer__image {
	-webkit-transition: opacity 0.3s 0.3s;
	transition: opacity 0.3s 0.3s;
}

.zoomer--active .zoomer__image {
	opacity: 0;
	-webkit-transition-delay: 0s;
	transition-delay: 0s;
}

.preview img {
	-webkit-transition: -webkit-transform 0.6s 0.3s;
	transition: transform 0.6s 0.3s;
	-webkit-transition-timing-function: cubic-bezier(0.2,1,0.3,1);
	transition-timing-function: cubic-bezier(0.2,1,0.3,1);
}

.zoomer--active .preview img {
	-webkit-transition: -webkit-transform 0.3s;
	transition: transform 0.3s;
}

.content {
	-webkit-transition: left 0s;
	transition: left 0s;
}

.content__item {
	-webkit-transition: opacity 0s;
	transition: opacity 0s;
}

.content,
.content__item {
	/* delay for content to disappear and zoomer to start transitioning back to 0 */
	-webkit-transition-delay: 0.3s;
	transition-delay: 0.3s;
}

.content--open,
.content__item--current {
	-webkit-transition: none;
	transition: none;
}

.content__item-img {
	-webkit-transition: -webkit-transform 0.4s;
	transition: transform 0.4s;
	-webkit-transition-timing-function: cubic-bezier(0.7,1,0.8,1);
	transition-timing-function: cubic-bezier(0.7,1,0.8,1);
}

.content__item--current .content__item-img {
	-webkit-transition-timing-function: cubic-bezier(0.2,1,0.3,1);
	transition-timing-function: cubic-bezier(0.2,1,0.3,1);
	-webkit-transition-duration: 1s;
	transition-duration: 1s;
}

.content__item-inner {
	-webkit-transition: -webkit-transform 0.6s, opacity 0.3s;
	transition: transform 0.6s, opacity 0.3s;
	-webkit-transition-timing-function: cubic-bezier(0.7,1,0.8,1), ease;
	transition-timing-function: cubic-bezier(0.7,1,0.8,1), ease;
}

.content__item--current .content__item-inner {
	-webkit-transition-timing-function: cubic-bezier(0.2,1,0.3,1), ease;
	transition-timing-function: cubic-bezier(0.2,1,0.3,1), ease;
	-webkit-transition-duration: 1.7s;
	transition-duration: 1.7s;
}

/* Media Queries */
@media screen and (max-width: 50em) {
	.content__item {
		display: block;
	}
	.content__item-img {
		max-width: calc(100% - 80px);
		max-height: 70vh;
	}
	.content h2 {
		font-size: 3em;
	}
	.content__item-inner {
		font-size: 82%;
		padding: 4em 3em 2em;
	}
}

کدهای javascript

;(function(window) {

	'use strict';

	var bodyEl = document.body, 
		docElem = window.document.documentElement,
		support = { transitions: Modernizr.csstransitions },
		// transition end event name
		transEndEventNames = { 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd', 'msTransition': 'MSTransitionEnd', 'transition': 'transitionend' },
		transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],
		onEndTransition = function( el, callback ) {
			var onEndCallbackFn = function( ev ) {
				if( support.transitions ) {
					if( ev.target != this ) return;
					this.removeEventListener( transEndEventName, onEndCallbackFn );
				}
				if( callback && typeof callback === 'function' ) { callback.call(this); }
			};
			if( support.transitions ) {
				el.addEventListener( transEndEventName, onEndCallbackFn );
			}
			else {
				onEndCallbackFn();
			}
		},
		// window sizes
		win = {width: window.innerWidth, height: window.innerHeight},
		// some helper vars to disallow scrolling
		lockScroll = false, xscroll, yscroll,
		scrollContainer = document.querySelector('.container'),
		// the main slider and its items
		sliderEl = document.querySelector('.slider'),
		items = [].slice.call(sliderEl.querySelectorAll('.slide')),
		// total number of items
		itemsTotal = items.length,
		// navigation controls/arrows
		navRightCtrl = sliderEl.querySelector('.button--nav-next'),
		navLeftCtrl = sliderEl.querySelector('.button--nav-prev'),
		zoomCtrl = sliderEl.querySelector('.button--zoom'),
		// the main content element
		contentEl = document.querySelector('.content'),
		// close content control
		closeContentCtrl = contentEl.querySelector('button.button--close'),
		// index of current item
		current = 0,
		// check if an item is "open"
		isOpen = false,
		isFirefox = typeof InstallTrigger !== 'undefined',
		// scale body when zooming into the items, if not Firefox (the performance in Firefox is not very good)
		bodyScale = isFirefox ? false : 3;

	// some helper functions:
	function scrollX() { return window.pageXOffset || docElem.scrollLeft; }
	function scrollY() { return window.pageYOffset || docElem.scrollTop; }
	// from http://www.sberry.me/articles/javascript-event-throttling-debouncing
	function throttle(fn, delay) {
		var allowSample = true;

		return function(e) {
			if (allowSample) {
				allowSample = false;
				setTimeout(function() { allowSample = true; }, delay);
				fn(e);
			}
		};
	}

	function init() {
		initEvents();
	}

	// event binding
	function initEvents() {
		// open items
		zoomCtrl.addEventListener('click', function() {
			openItem(items[current]);
		});

		// close content
		closeContentCtrl.addEventListener('click', closeContent);

		// navigation
		navRightCtrl.addEventListener('click', function() { navigate('right'); });
		navLeftCtrl.addEventListener('click', function() { navigate('left'); });

		// window resize
		window.addEventListener('resize', throttle(function(ev) {
			// reset window sizes
			win = {width: window.innerWidth, height: window.innerHeight};

			// reset transforms for the items (slider items)
			items.forEach(function(item, pos) {
				if( pos === current ) return;
				var el = item.querySelector('.slide__mover');
				dynamics.css(el, { translateX: el.offsetWidth });
			});
		}, 10));

		// keyboard navigation events
		document.addEventListener( 'keydown', function( ev ) {
			if( isOpen ) return; 
			var keyCode = ev.keyCode || ev.which;
			switch (keyCode) {
				case 37:
					navigate('left');
					break;
				case 39:
					navigate('right');
					break;
			}
		} );
	}

	// opens one item
	function openItem(item) {
		if( isOpen ) return;
		isOpen = true;

		// the element that will be transformed
		var zoomer = item.querySelector('.zoomer');
		// slide screen preview
		classie.add(zoomer, 'zoomer--active');
		// disallow scroll
		scrollContainer.addEventListener('scroll', noscroll);
		// apply transforms
		applyTransforms(zoomer);
		// also scale the body so it looks the camera moves to the item.
		if( bodyScale ) {
			dynamics.animate(bodyEl, { scale: bodyScale }, { type: dynamics.easeInOut, duration: 500 });
		}
		// after the transition is finished:
		onEndTransition(zoomer, function() {
			// reset body transform
			if( bodyScale ) {
				dynamics.stop(bodyEl);
				dynamics.css(bodyEl, { scale: 1 });
				
				// fix for safari (allowing fixed children to keep position)
				bodyEl.style.WebkitTransform = 'none';
				bodyEl.style.transform = 'none';
			}
			// no scrolling
			classie.add(bodyEl, 'noscroll');
			classie.add(contentEl, 'content--open');
			var contentItem = document.getElementById(item.getAttribute('data-content'))
			classie.add(contentItem, 'content__item--current');
			classie.add(contentItem, 'content__item--reset');


			// reset zoomer transform - back to its original position/transform without a transition
			classie.add(zoomer, 'zoomer--notrans');
			zoomer.style.WebkitTransform = 'translate3d(0,0,0) scale3d(1,1,1)';
			zoomer.style.transform = 'translate3d(0,0,0) scale3d(1,1,1)';
		});
	}

	// closes the item/content
	function closeContent() {
		var contentItem = contentEl.querySelector('.content__item--current'),
			zoomer = items[current].querySelector('.zoomer');

		classie.remove(contentEl, 'content--open');
		classie.remove(contentItem, 'content__item--current');
		classie.remove(bodyEl, 'noscroll');
				
		if( bodyScale ) {
			// reset fix for safari (allowing fixed children to keep position)
			bodyEl.style.WebkitTransform = '';
			bodyEl.style.transform = '';
		}

		/* fix for safari flickering */
		var nobodyscale = true;
		applyTransforms(zoomer, nobodyscale);
		/* fix for safari flickering */

		// wait for the inner content to finish the transition
		onEndTransition(contentItem, function(ev) {
			classie.remove(this, 'content__item--reset');
			
			// reset scrolling permission
			lockScroll = false;
			scrollContainer.removeEventListener('scroll', noscroll);

			/* fix for safari flickering */
			zoomer.style.WebkitTransform = 'translate3d(0,0,0) scale3d(1,1,1)';
			zoomer.style.transform = 'translate3d(0,0,0) scale3d(1,1,1)';
			/* fix for safari flickering */
			
			// scale up - behind the scenes - the item again (without transition)
			applyTransforms(zoomer);
			
			// animate/scale down the item
			setTimeout(function() {	
				classie.remove(zoomer, 'zoomer--notrans');
				classie.remove(zoomer, 'zoomer--active');
				zoomer.style.WebkitTransform = 'translate3d(0,0,0) scale3d(1,1,1)';
				zoomer.style.transform = 'translate3d(0,0,0) scale3d(1,1,1)';
			}, 25);

			if( bodyScale ) {
				dynamics.css(bodyEl, { scale: bodyScale });
				dynamics.animate(bodyEl, { scale: 1 }, {
					type: dynamics.easeInOut,
					duration: 500
				});
			}

			isOpen = false;
		});
	}

	// applies the necessary transform value to scale the item up
	function applyTransforms(el, nobodyscale) {
		// zoomer area and scale value
		var zoomerArea = el.querySelector('.zoomer__area'), 
			zoomerAreaSize = {width: zoomerArea.offsetWidth, height: zoomerArea.offsetHeight},
			zoomerOffset = zoomerArea.getBoundingClientRect(),
			scaleVal = zoomerAreaSize.width/zoomerAreaSize.height < win.width/win.height ? win.width/zoomerAreaSize.width : win.height/zoomerAreaSize.height;

		if( bodyScale && !nobodyscale ) {
			scaleVal /= bodyScale; 
		}

		// apply transform
		el.style.WebkitTransform = 'translate3d(' + Number(win.width/2 - (zoomerOffset.left+zoomerAreaSize.width/2)) + 'px,' + Number(win.height/2 - (zoomerOffset.top+zoomerAreaSize.height/2)) + 'px,0) scale3d(' + scaleVal + ',' + scaleVal + ',1)';
		el.style.transform = 'translate3d(' + Number(win.width/2 - (zoomerOffset.left+zoomerAreaSize.width/2)) + 'px,' + Number(win.height/2 - (zoomerOffset.top+zoomerAreaSize.height/2)) + 'px,0) scale3d(' + scaleVal + ',' + scaleVal + ',1)';
	}

	// navigate the slider
	function navigate(dir) {
		var itemCurrent = items[current],
			currentEl = itemCurrent.querySelector('.slide__mover'),
			currentTitleEl = itemCurrent.querySelector('.slide__title');

		// update new current value
		if( dir === 'right' ) {
			current = current < itemsTotal-1 ? current + 1 : 0;
		}
		else {
			current = current > 0 ? current - 1 : itemsTotal-1;
		}

		var itemNext = items[current],
			nextEl = itemNext.querySelector('.slide__mover'),
			nextTitleEl = itemNext.querySelector('.slide__title');
		
		// animate the current element out
		dynamics.animate(currentEl, { opacity: 0, translateX: dir === 'right' ? -1*currentEl.offsetWidth/2 : currentEl.offsetWidth/2, rotateZ: dir === 'right' ? -10 : 10 }, {
			type: dynamics.spring,
			duration: 2000,
			friction: 600,
			complete: function() {
				dynamics.css(itemCurrent, { opacity: 0, visibility: 'hidden' });
			}
		});

		// animate the current title out
		dynamics.animate(currentTitleEl, { translateX: dir === 'right' ? -250 : 250, opacity: 0 }, {
			type: dynamics.bezier,
			points: [{"x":0,"y":0,"cp":[{"x":0.2,"y":1}]},{"x":1,"y":1,"cp":[{"x":0.3,"y":1}]}],
			duration: 450
		});

		// set the right properties for the next element to come in
		dynamics.css(itemNext, { opacity: 1, visibility: 'visible' });
		dynamics.css(nextEl, { opacity: 0, translateX: dir === 'right' ? nextEl.offsetWidth/2 : -1*nextEl.offsetWidth/2, rotateZ: dir === 'right' ? 10 : -10 });

		// animate the next element in
		dynamics.animate(nextEl, { opacity: 1, translateX: 0 }, {
			type: dynamics.spring,
			duration: 2000,
			friction: 600,
			complete: function() {
				items.forEach(function(item) { classie.remove(item, 'slide--current'); });
				classie.add(itemNext, 'slide--current');
			}
		});

		// set the right properties for the next title to come in
		dynamics.css(nextTitleEl, { translateX: dir === 'right' ? 250 : -250, opacity: 0 });
		// animate the next title in
		dynamics.animate(nextTitleEl, { translateX: 0, opacity: 1 }, {
			type: dynamics.bezier,
			points: [{"x":0,"y":0,"cp":[{"x":0.2,"y":1}]},{"x":1,"y":1,"cp":[{"x":0.3,"y":1}]}],
			duration: 650
		});
	}

	// disallow scrolling (on the scrollContainer)
	function noscroll() {
		if(!lockScroll) {
			lockScroll = true;
			xscroll = scrollContainer.scrollLeft;
			yscroll = scrollContainer.scrollTop;
		}
		scrollContainer.scrollTop = yscroll;
		scrollContainer.scrollLeft = xscroll;
	}

	init();

})(window);

 

چه امتیازی برای این مقاله میدهید؟

خیلی بد
بد
متوسط
خوب
عالی
5 از 1 رای

/@hesammousavi
حسام موسوی
طراح و برنامه نویس

بیشتر از ۱۵ سال هست که در حال برنامه‌نویسی و انجام پروژه های مختلف هستم و ۱۰ سالی هست که آموزش برنامه‌نویسی به علاقمندان حوزه برنامه نویسی میدیم در همه این مدت الان عاشق کدزنی و چالش‌های پروژه‌های مختلفم. به تدریس علاقه خاصی دارم و دوست دارم دانشی که در این راه بدست آوردم را در اختیار دیگران هم قرار بدم. 

دیدگاه و پرسش

برای ارسال دیدگاه لازم است وارد شده یا ثبت‌نام کنید ورود یا ثبت‌نام

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

حسام موسوی

طراح و برنامه نویس

مقالات برگزیده

مقالات برگزیده را از این قسمت میتوانید ببینید

مشاهده همه مقالات