- Notifications
You must be signed in to change notification settings - Fork 22
CSS3之3d transform #2
Copy link
Copy link
Open
Milestone
Description
Metadata
Metadata
Assignees
Labels
No labels
') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })();
原文地址: Intro to css 3D transforms
前言:
作者的这个introduction已经写了有好几年了,我今年(而且今年都快过去了)才看到...果真是渣渣...那句话,人丑朋友又少真的是要多读书。不过我觉得我还是得厚着大脸皮敲下去...
三维世界的坐标系
文章开始之前先来张坐标系图好让大家有个3D概念

透视,perspective属性
为了激活3D属性,需要对元素声明
perspective属性。有两种声明的方式:作为属性transform的值和transform一起声明,就同如下代码一样
直接使用 perspective属性 声明
例子1: 点击访问demo
这两种方式都能产生3D效果,看上去是产生了一样的效果,但是其实两者还是不同的。transform值的形式适用于单个元素的3D转换效果,就像上个例子一样。但是如果应用于多个元素的话,发生变换的元素并不会表现出一致的效果。因为如果对每个不同位置的元素声明一样的transform属性值,那么他们就会拥有个各自的3D空间的基点了。为了解决这个问题,需要对父元素声明
perspective属性,使每个子元素共享一个3D空间了。例子2: 点击访问demo

PS: 看不出效果的话,可以改变下perspective的值,这样看到的差别会明显一点
perspective值的大小决定了3D效果的强弱程度。就像人看物体一样,perspective值越大,代表物体离眼睛的距离越远,这样看到的物体就越小。perspective:2000px,产生的效果就像我们用望远镜看一个很远很远的物体,perspective: 100px; 则会让物体看起来很大,就像一只小虫看巨大的物体一样。
元素的3D空间的默认基点坐标位于元素中央。但是可以通过
perspective-origin属性来修改:perspective-origin: 25% 75%;例子3 : 点击访问demo
浏览器支持情况
目前的浏览器支持情况如下: 详情请点击查看

3D transform functions
废话我就不翻译了。。。
3D转换和2D转换方法基本相同,下面就是3D转换方法:
但是不同的是, translateX()方法是使一个元素沿着水平X轴坐标旋转,translateZ()则是沿着Z坐标轴,可以使物体在3D空间从前往后移动。值为正数且越大则元素离屏幕越近,负数则代表离屏幕远。
rotate方法使物体在相应的坐标系进行旋转。不过注意哦,rotateX可不是从二维空间中的从左到右的旋转,而是围绕真文章最开头给大家温习的那张3D图中的X轴旋转,具体看下面的例子。
3D transform也提供了一些简写方法,使用这些方法需要同时声明三个维度的参数:
提示: 这些3D方法都能够触发Safari的硬件加速,Dean Jackson, CSS 3D transform 技术规范的作者以及主要的Webkit成员这么写道:
“实际上,任何transform的3D操作都会触发硬件加速,即使实际只做了2D转换或者什么也没有做(就像translate3d(0,0,0))。但是这只是目前如此并不代表将来就不会发生变化,这也就是为什么我们没有形成文档或者鼓励这样做的原因。但是这在有些场景下确实很有帮助,可以显著提高渲染的性能。”
这里作者为了简单起见,例子上都只是用了一些基本的转换方法,但是如果你需要在IOS或者Safari的生产环境下使用CSS的话,最好使用foo3d()(指的3D transform的简写方法)来获取最好的渲染性能。
活学活用
1. 卡片翻转
现在大家应该都知道了如何制作3D效果。那就先实现个简单卡片翻转的例子吧。
先看看效果: 请点击
.container 作为舞台元素,声明
perspective:800px;属性现在#card就可以在container的3D空间内进行各种变换了,声明
width: 100%; and height: 100%;是为了保证transform-origin为container的中央位置transform-style属性有两个参数,flat|preserve-3d. 前者flat为默认值,表示平面的;后者preserve-3d表示3D透视。一般而言,该声明应用在3D变换的兄弟元素们的父元素上,也就是舞台元素。
backface-visibility: hidden;当前面元素遮挡住后面的元素时,声明这个属性就可以产生遮挡的效果。首先视觉上我们只能看到.front的卡片,所以需要将.back的卡片沿着Y轴旋转180度至后方,当点击flip按钮的时候,直接让#card再沿着Y轴旋转180度,这个时候front卡片就到视线后方而back卡就被我们看到了。
如果我们想要改变旋转轴的位置呢? 这就是transform-origin的作用了,稍作修改就可以达到以下的效果。
我要更炫点: 请点击
2. 立方体
DEMO:
cube1
cube2
这个例子主要向大家介绍下
translateZ()方法,它可以帮你理解透视位置。demo**但是这里需要注意的是translateZ 和 rotate 方法的顺序,顺序的不同会产生不一样的效果。**可以通过以下例子好好感受下~
translateZ
3. 旋转木马
旋转木马
这里主要向大家介绍旋转木马效果计算各个面板translateZ值的方法:
那问题来了,怎么计算translateZ的值呢? 其实很简单,当然不是凭直觉随便选出来的那种简单,因为它还是有公式的,那就用下面这张图来说明吧:


然后我们就可以计算出 r 的值了~