ในชุดนี้เราทำแถบเลื่อนรูปภาพโดยไม่มีอะไรนอกจาก HTML และ CSS แนวคิดคือเราสามารถใช้มาร์กอัปเดียวกันแต่ใช้ CSS ต่างกันเพื่อให้ได้ผลลัพธ์ที่แตกต่างกันอย่างมาก ไม่ว่าเราจะใส่รูปภาพกี่รูปก็ตาม เราเริ่มด้วยแถบเลื่อนวงกลมที่หมุนได้ไม่รู้จบ คล้ายกับตัวหมุนที่อยู่ไม่สุขที่เก็บรูปภาพ จากนั้นเราก็สร้างภาพที่พลิกดูกองภาพถ่าย
คราวนี้เรากำลังดำดิ่งสู่มิติที่สาม ในตอนแรกจะดูยาก แต่โค้ดจำนวนมากที่เรากำลังดูนั้นตรงกับสิ่งที่เราใช้ในสองบทความแรกในซีรีส์นี้ โดยมีการปรับเปลี่ยนบางอย่าง ดังนั้น หากคุณเพิ่งเข้าสู่ซีรีส์นี้ ฉันขอแนะนำให้ตรวจสอบเนื้อหาอื่นๆ เกี่ยวกับแนวคิดที่เราใช้ที่นี่
ชุดตัวเลื่อน CSS
นี่คือสิ่งที่เราตั้งเป้าไว้:
เมื่อมองแวบแรก ดูเหมือนว่าเรามีลูกบาศก์หมุนที่มีสี่ภาพ แต่ในความเป็นจริง เรากำลังจัดการกับภาพทั้งหมดหกภาพ นี่คือแถบเลื่อนจากมุมอื่น:
ตอนนี้เรามีภาพที่ดีสำหรับการจัดเรียงภาพแล้ว เรามาแยกรหัสเพื่อดูว่าเราไปถึงที่นั่นได้อย่างไร
การตั้งค่าพื้นฐาน
HTML เดียวกันกับแถบเลื่อนที่เหลือที่เราใช้กับแถบเลื่อนอื่นๆ:
และอีกครั้ง เรากำลังใช้ CSS Grid เพื่อวางภาพในสแต็ก โดยวางซ้อนกัน:
.gallery {
display: grid;
}
.gallery > img {
grid-area: 1 / 1;
width: 160px;
aspect-ratio: 1;
object-fit: cover;
}
แอนิเมชั่น
ตรรกะสำหรับแถบเลื่อนนี้คล้ายกับ แถบเลื่อนวงกลมจากบทความแรก. ในความเป็นจริง หากคุณตรวจสอบวิดีโอด้านบนอีกครั้ง คุณจะเห็นว่าภาพถูกวางในลักษณะที่สร้างรูปหลายเหลี่ยม หลังจากหมุนครบแล้ว จะกลับไปที่ภาพแรก
เราพึ่งพา CSS transform-origin
และ animation-delay
คุณสมบัติสำหรับแถบเลื่อนแรกนั้น ภาพเคลื่อนไหวเดียวกันนี้ใช้กับองค์ประกอบภาพทั้งหมด ซึ่งหมุนรอบจุดเดียวกัน จากนั้น ด้วยการใช้การหน่วงเวลาที่ต่างกัน เราจะวางภาพทั้งหมดรอบวงกลมขนาดใหญ่ได้อย่างถูกต้อง
การใช้งานจะแตกต่างกันเล็กน้อยสำหรับแถบเลื่อน 3 มิติของเรา โดยใช้ transform-origin
จะไม่ทำงานที่นี่เพราะเรากำลังทำงานใน 3D ดังนั้นเราจะใช้ transform
แทนที่จะวางภาพทั้งหมดให้ถูกต้อง จากนั้นหมุนคอนเทนเนอร์
เรากำลังติดต่อ Sass อีกครั้งเพื่อให้เราสามารถวนซ้ำจำนวนภาพและใช้การแปลงของเรา:
@for $i from 1 to ($n + 1) {
.gallery > img:nth-child(#{$i}) {
transform:
rotate(#{360*($i - 1) / $n}deg) /* 1 */
translateY(50% / math.tan(180deg / $n)) /* 2 */
rotateX(90deg); /* 3 */
}
}
คุณอาจสงสัยว่าทำไมเราถึงกระโดดเข้าหา Sass โดยตรง เราเริ่มต้นด้วยจำนวนรูปภาพที่แน่นอนโดยใช้วานิลลา CSS ในบทความอื่นๆ ก่อนที่จะสรุปรหัสด้วย Sass เพื่อพิจารณาจำนวนใดๆ (N
) ของรูปภาพ ฉันคิดว่าคุณคงเข้าใจความคิดแล้ว และเราสามารถตัดงานการค้นพบทั้งหมดนั้นออกเพื่อนำไปใช้งานจริงได้
พื้นที่ transform
คุณสมบัติมีค่าสามค่าซึ่งฉันได้แสดงไว้ที่นี่:
ก่อนอื่นเราหมุนภาพทั้งหมดที่อยู่ด้านบนกัน มุมของการหมุนขึ้นอยู่กับจำนวนภาพ สำหรับ N
ภาพเราเพิ่มขึ้นเท่ากับ 360deg/N
. ถ้าอย่างนั้นเรา translate
ภาพทั้งหมดด้วยจำนวนที่เท่ากันในลักษณะที่ทำให้จุดกึ่งกลางบรรจบกันที่ด้านข้าง
มีรูปทรงเรขาคณิตที่น่าเบื่อบางอย่างที่ช่วยอธิบายวิธีการทำงานทั้งหมดนี้ แต่ระยะทางเท่ากับ 50%/tan(180deg/N)
. เราจัดการกับสมการที่คล้ายกันเมื่อสร้างแถบเลื่อนวงกลม ( transform-origin: 50% 50%/sin(180deg/N)
).
สุดท้าย เราหมุนภาพรอบแกน x โดย 90deg
เพื่อให้ได้การจัดที่เราต้องการ นี่คือวิดีโอที่แสดงให้เห็นว่าการหมุนเวียนครั้งล่าสุดเป็นอย่างไร:
ตอนนี้สิ่งที่เราต้องทำคือหมุนคอนเทนเนอร์ทั้งหมดเพื่อสร้างแถบเลื่อนที่ไม่มีที่สิ้นสุดของเรา
.gallery {
transform-style: preserve-3d;
--_t: perspective(280px) rotateX(-90deg);
animation: r 12s cubic-bezier(.5, -0.2, .5, 1.2) infinite;
}
@keyframes r {
0%, 3% {transform: var(--_t) rotate(0deg); }
@for $i from 1 to $n {
#{($i/$n)*100 - 2}%,
#{($i/$n)*100 + 3}% {
transform: var(--_t) rotate(#{($i / $n) * -360}deg);
}
}
98%, 100% { transform: var(--_t) rotate(-360deg); }
}
โค้ดนั้นอาจเข้าใจยาก ดังนั้นเรามาย้อนกลับไปดูแอนิเมชันที่เราสร้างสำหรับแถบเลื่อนวงกลมกันอีกครั้ง นี่คือสิ่งที่เราเขียนไว้ในบทความแรก:
.gallery {
animation: m 12s cubic-bezier(.5, -0.2, .5, 1.2) infinite;
}
@keyframes m {
0%, 3% { transform: rotate(0); }
@for $i from 1 to $n {
#{($i / $n) * 100 - 2}%,
#{($i / $n) * 100 + 3}% {
transform: rotate(#{($i / $n) * -360}deg);
}
}
98%, 100% { transform: rotate(-360deg); }
}
คีย์เฟรมเกือบจะเหมือนกัน เรามีค่าเปอร์เซ็นต์เท่ากัน วงเดียวกัน และการหมุนรอบเดียวกัน
ทำไมเหมือนกันทั้งคู่ เพราะตรรกะของพวกเขาเหมือนกัน ในทั้งสองกรณี รูปภาพถูกจัดเรียงเป็นรูปวงกลม และเราจำเป็นต้องหมุนทั้งหมดเพื่อแสดงแต่ละภาพ นั่นเป็นวิธีที่ฉันสามารถคัดลอกคีย์เฟรมจากแถบเลื่อนวงกลมและใช้รหัสเดียวกันนั้นสำหรับแถบเลื่อน 3 มิติของเรา ข้อแตกต่างเพียงอย่างเดียวคือเราต้องหมุนภาชนะตาม -90deg
ตามแนวแกน x เพื่อดูภาพ เนื่องจากเราหมุนไปแล้ว 90deg
บนแกนเดียวกัน จากนั้นเราเพิ่มสัมผัสของ perspective
เพื่อให้ได้เอฟเฟ็กต์ 3 มิติ
แค่นั้นแหละ! สไลเดอร์ของเราเสร็จแล้ว นี่คือการสาธิตแบบเต็มอีกครั้ง สิ่งที่คุณต้องทำคือเพิ่มรูปภาพได้มากเท่าที่คุณต้องการและอัปเดตตัวแปรหนึ่งตัวเพื่อดำเนินการต่อ
แถบเลื่อน 3 มิติแนวตั้ง
เนื่องจากเรากำลังเล่นในพื้นที่ 3 มิติ ทำไมไม่ลองสร้างแถบเลื่อนรุ่นก่อนหน้าในแนวตั้งดูล่ะ อันสุดท้ายหมุนไปตามแกน z แต่เราสามารถเลื่อนไปตามแกน x ได้หากต้องการ
หากคุณเปรียบเทียบโค้ดของแถบเลื่อนนี้ทั้งสองเวอร์ชัน คุณอาจไม่เห็นความแตกต่างในทันทีเพราะเป็นอักขระเพียงตัวเดียว! ฉันแทนที่ rotate()
กับ rotateX()
ภายในคีย์เฟรมและรูปภาพ transform
. แค่นั้นแหละ!
ควรสังเกตว่า rotate()
เทียบเท่ากับ rotateZ()
ดังนั้น โดยการเปลี่ยนแกนจาก Z
ไปยัง X
เราเปลี่ยนแถบเลื่อนจากแนวนอนเป็นแนวตั้ง
ตัวเลื่อนลูกบาศก์
เราไม่สามารถพูดถึง 3D ใน CSS ได้หากไม่มี พูดถึงลูกบาศก์. และใช่ นั่นหมายความว่าเรากำลังจะสร้างแถบเลื่อนอีกเวอร์ชันหนึ่ง
แนวคิดเบื้องหลังแถบเลื่อนเวอร์ชันนี้คือการสร้างรูปทรงลูกบาศก์จริงพร้อมรูปภาพและหมุนสิ่งที่เต็มไปรอบๆ แกนต่างๆ เนื่องจากมันเป็นลูกบาศก์ เราจึงต้องเผชิญกับหกหน้า เราจะใช้ภาพหกภาพ หนึ่งภาพสำหรับแต่ละหน้าของลูกบาศก์ ดังนั้นไม่ใช่ Sass แต่กลับไปที่วานิลลา CSS
อนิเมชั่นนั้นค่อนข้างล้นหลามใช่ไหม คุณจะเริ่มต้นที่ไหน
เรามีหกหน้า ดังนั้นเราต้องทำการหมุนอย่างน้อยหกครั้งเพื่อให้แต่ละภาพได้รับการหมุน อันที่จริง เราต้องการการหมุนห้ารอบ — อันสุดท้ายจะนำเรากลับไปที่ใบหน้ารูปแรก ถ้าคุณไปคว้าลูกบาศก์รูบิค — หรือวัตถุรูปทรงลูกบาศก์อื่น ๆ เช่น ลูกเต๋า — แล้วหมุนมันด้วยมือของคุณ คุณจะมีความคิดที่ดีว่าเรากำลังทำอะไรอยู่
.gallery {
--s: 250px; /* the size */
transform-style: preserve-3d;
--_p: perspective(calc(2.5*var(--s)));
animation: r 9s infinite cubic-bezier(.5, -0.5, .5, 1.5);
}
@keyframes r {
0%, 3% { transform: var(--_p); }
14%, 19% { transform: var(--_p) rotateX(90deg); }
31%, 36% { transform: var(--_p) rotateX(90deg) rotateZ(90deg); }
47%, 52% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg); }
64%, 69% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg); }
81%, 86% { transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg) rotateZ(90deg); }
97%, 100%{ transform: var(--_p) rotateX(90deg) rotateZ(90deg) rotateY(-90deg) rotateX(90deg) rotateZ(90deg) rotateY(-90deg); }
}
พื้นที่ transform
คุณสมบัติเริ่มต้นด้วยการหมุนเป็นศูนย์ และในแต่ละสถานะ เราจะเพิ่มการหมุนใหม่บนแกนใดแกนหนึ่งจนกระทั่งเราหมุนครบหกรอบ จากนั้นเราจะกลับไปที่ภาพแรก
อย่าลืมตำแหน่งของภาพของเรา แต่ละอันถูกนำไปใช้กับใบหน้าของลูกบาศก์โดยใช้ transform
:
.gallery img {
grid-area: 1 / 1;
width: var(--s);
aspect-ratio: 1;
object-fit: cover;
transform: var(--_t,) translateZ(calc(var(--s) / 2));
}
.gallery img:nth-child(2) { --_t: rotateX(-90deg); }
.gallery img:nth-child(3) { --_t: rotateY( 90deg) rotate(-90deg); }
.gallery img:nth-child(4) { --_t: rotateX(180deg) rotate( 90deg); }
.gallery img:nth-child(5) { --_t: rotateX( 90deg) rotate( 90deg); }
.gallery img:nth-child(6) { --_t: rotateY(-90deg); }
คุณอาจคิดว่ามีตรรกะที่ซับซ้อนแปลกๆ อยู่เบื้องหลังค่าที่ฉันใช้อยู่ใช่ไหม ก็ไม่ ทั้งหมดที่ฉันทำคือเปิด DevTools และเล่นกับค่าการหมุนที่แตกต่างกันสำหรับแต่ละภาพจนกว่าฉันจะทำได้ถูกต้อง อาจฟังดูงี่เง่า แต่เดี๋ยวก่อน มันได้ผล — โดยเฉพาะอย่างยิ่งเมื่อเรามีจำนวนภาพที่แน่นอน และเราไม่ได้มองหาสิ่งที่รองรับ N
ภาพ
อันที่จริง ลืมค่าต่างๆ ที่ฉันใช้อยู่และพยายามจัดตำแหน่งด้วยตัวคุณเองในแบบฝึกหัด เริ่มจากนำภาพทั้งหมดมาซ้อนกัน เปิด DevTools แล้วไปกันเลย! คุณอาจจะลงเอยด้วยรหัสอื่นซึ่งก็ไม่เป็นไร การวางตำแหน่งรูปภาพอาจมีหลายวิธี
เคล็ดลับกับเครื่องหมายจุลภาคใน
var()
? มันเป็นการพิมพ์ผิด?
มันไม่ใช่การพิมพ์ผิด ดังนั้นอย่าลบออก! หากคุณลบออก คุณจะสังเกตเห็นว่ามีผลกับตำแหน่งของภาพแรก คุณจะเห็นว่าในรหัสของฉันที่ฉันกำหนดไว้ --_t
สำหรับภาพทั้งหมดยกเว้นภาพแรกเพราะฉันต้องการคำแปลเท่านั้น เครื่องหมายจุลภาคนั้นทำให้ตัวแปรถอยกลับไปเป็นค่าว่าง หากไม่มีเครื่องหมายจุลภาค เราจะไม่มีทางเลือกสำรองและค่าทั้งหมดจะไม่ถูกต้อง
จาก ข้อมูลจำเพาะ:
หมายเหตุ: นั่นคือ
var(--a,)
เป็นฟังก์ชันที่ถูกต้อง โดยระบุว่า ถ้า--a
คุณสมบัติที่กำหนดเองไม่ถูกต้องหรือหายไป, thevar()
` ควรจะแทนที่ด้วยอะไร
ตัวเลื่อนลูกบาศก์แบบสุ่ม
การสุ่มเล็กน้อยอาจเป็นส่วนเสริมที่ดีสำหรับแอนิเมชันประเภทนี้ ดังนั้น แทนที่จะหมุนลูกบาศก์ตามลำดับ เราสามารถทอยลูกเต๋าได้ตามที่พูด และปล่อยให้ลูกบาศก์หมุนไปตามทิศทางของมัน
เย็นใช่มั้ย? ฉันไม่รู้เกี่ยวกับคุณ แต่ฉันชอบเวอร์ชั่นนี้มากกว่า! มันน่าสนใจกว่าและช่วงการเปลี่ยนภาพก็น่าพอใจที่จะดู และคาดเดาอะไร คุณสามารถเล่นกับค่าต่าง ๆ เพื่อสร้างตัวเลื่อนคิวบ์แบบสุ่มของคุณเอง!
ตรรกะนั้นไม่ได้เกิดขึ้นจริงโดยบังเอิญเลย — มันดูเหมือนเป็นอย่างนั้น คุณกำหนดก transform
ในแต่ละคีย์เฟรมที่ให้คุณแสดงใบหน้าเดียว และ... ก็แค่นั้นจริงๆ! คุณสามารถเลือกคำสั่งใด ๆ ที่คุณต้องการ
@keyframes r {
0%, 3% { transform: var(--_p) rotate3d( 0, 0, 0, 0deg); }
14%,19% { transform: var(--_p) rotate3d(-1, 1, 0,180deg); }
31%,36% { transform: var(--_p) rotate3d( 0,-1, 0, 90deg); }
47%,52% { transform: var(--_p) rotate3d( 1, 0, 0, 90deg); }
64%,69% { transform: var(--_p) rotate3d( 1, 0, 0,-90deg); }
81%,86% { transform: var(--_p) rotate3d( 0, 1, 0, 90deg); }
97%,100% { transform: var(--_p) rotate3d( 0, 0, 0, 0deg); }
}
ฉันใช้ rotate3d()
ครั้งนี้ แต่ฉันยังคงพึ่งพา DevTools เพื่อค้นหาค่าที่รู้สึกว่า "ใช่" สำหรับฉัน อย่าพยายามค้นหาความสัมพันธ์ระหว่างคีย์เฟรมเพราะไม่มีเลย ฉันกำลังกำหนดการแปลงแยกกันแล้วดูผลลัพธ์ "สุ่ม" ตรวจสอบให้แน่ใจว่าภาพแรกคือเฟรมแรกและเฟรมสุดท้ายตามลำดับ และแสดงรูปภาพที่แตกต่างกันในแต่ละเฟรมอื่นๆ
คุณไม่จำเป็นต้องใช้ rotate3d()
แปลงร่างเหมือนที่ฉันทำ คุณยังสามารถเชื่อมโยงการหมุนต่างๆ เข้าด้วยกันได้เหมือนกับที่เราทำในตัวอย่างที่แล้ว เล่นไปรอบ ๆ และดูว่าคุณสามารถทำอะไรได้บ้าง! ฉันจะรอให้คุณแบ่งปันเวอร์ชันของคุณกับฉันในส่วนความคิดเห็น!
ตัดขึ้น
ฉันหวังว่าคุณจะสนุกกับซีรีส์เล็ก ๆ นี้ เราสร้างแถบเลื่อนที่สนุก (และตลก) ในขณะที่เรียนรู้มากมายเกี่ยวกับแนวคิด CSS ทุกประเภทไปพร้อมกัน ตั้งแต่การวางตารางและลำดับการซ้อน ไปจนถึงการหน่วงเวลาและการแปลงภาพเคลื่อนไหว เรายังต้องเล่นกับ Sass เพื่อวนซ้ำองค์ประกอบต่างๆ
และเราทำทั้งหมดนี้ด้วย HTML เดียวกันทุกประการสำหรับแถบเลื่อนแต่ละตัวที่เราสร้างขึ้น มันเจ๋งแค่ไหน? CSS นั้นทรงพลังและสามารถทำได้หลายอย่างโดยไม่ต้องใช้ JavaScript ช่วย