直接加空格方式效果不理想,改用js和css配合来加空格
This commit is contained in:
parent
1253d6be4b
commit
80a044fa7c
|
@ -1,6 +1,6 @@
|
|||
if banner
|
||||
.banner
|
||||
p.text-body !{banner}
|
||||
p.text-body.translated-cn !{banner}
|
||||
else if intro
|
||||
.banner
|
||||
p.text-body !{intro}
|
||||
p.text-body.translated-cn !{intro}
|
||||
|
|
|
@ -20,7 +20,7 @@ script(src="/resources/js/vendor/angular-material.min.js")
|
|||
|
||||
|
||||
<!-- Angular.io Site JS -->
|
||||
script(src="/resources/js/translate.js")
|
||||
script(src="/translate/cn/translate.js")
|
||||
script(src="/resources/js/site.js")
|
||||
script(src="/resources/js/controllers/app-controller.js")
|
||||
script(src="/resources/js/controllers/resources-controller.js")
|
||||
|
|
|
@ -6,15 +6,15 @@ include ../_util-fns
|
|||
that call attention where it's needed. Well-designed animations can make a UI not only
|
||||
more fun but also easier to use.
|
||||
|
||||
动画是现代 Web 应用设计中一个很重要的方面。我们希望用户界面能在不同的状态之间更平滑的转场。如果需要,还可以用适当的动画来吸引注意力。
|
||||
设计良好的动画不但会让 UI 更有趣,还会让它更容易使用。
|
||||
动画是现代Web应用设计中一个很重要的方面。我们希望用户界面能在不同的状态之间更平滑的转场。如果需要,还可以用适当的动画来吸引注意力。
|
||||
设计良好的动画不但会让UI更有趣,还会让它更容易使用。
|
||||
|
||||
Angular's animation system gives us what we need to make the kinds of animations we want.
|
||||
We can build animations that run with the same kind of native performance that we're used
|
||||
to with pure CSS animations. But we can also have our animation logic tightly integrated
|
||||
with the rest of our application code, where they can be easily triggered and controlled.
|
||||
|
||||
Angular 的动画系统赋予了我们制作各种动画效果的能力,以构建出与原生 CSS 动画性能相同的动画。
|
||||
Angular的动画系统赋予了我们制作各种动画效果的能力,以构建出与原生CSS动画性能相同的动画。
|
||||
但我们又额外获得了让动画逻辑与其它应用代码紧紧集成在一起的能力,这让动画可以被更容易的触发与控制。
|
||||
|
||||
.alert.is-helpful
|
||||
|
@ -22,17 +22,17 @@ include ../_util-fns
|
|||
Angular animations are built on top of the standard [Web Animations API](https://w3c.github.io/web-animations/)
|
||||
and they run natively on [browsers that support it](http://caniuse.com/#feat=web-animation).
|
||||
|
||||
Angular 动画是基于标准的 [Web 动画 API(Web Animations API)](https://w3c.github.io/web-animations/) 构建的,它们在[支持此 API 的浏览器中](http://caniuse.com/#feat=web-animation)会用原生方式工作。
|
||||
Angular动画是基于标准的[Web动画API(Web Animations API)](https://w3c.github.io/web-animations/)构建的,它们在[支持此API的浏览器中](http://caniuse.com/#feat=web-animation)会用原生方式工作。
|
||||
|
||||
For other browsers, a polyfill is required. Grab
|
||||
[`web-animations.min.js` from here](https://github.com/web-animations/web-animations-js) and
|
||||
add it to your page.
|
||||
|
||||
至于其它浏览器,就需要一个填充库(polyfill)了。你可以[从这里获取 `web-animations.min.js`](https://github.com/web-animations/web-animations-js),并把它加入你的页面中。
|
||||
至于其它浏览器,就需要一个填充库(polyfill)了。你可以[从这里获取`web-animations.min.js`](https://github.com/web-animations/web-animations-js),并把它加入你的页面中。
|
||||
|
||||
A more lightweight polyfill maintained by the Angular team is coming soon.
|
||||
|
||||
Angular 开发组还在开发另一个更加轻量级的填充库,预计不久就会完工。
|
||||
Angular开发组还在开发另一个更加轻量级的填充库,预计不久就会完工。
|
||||
|
||||
:marked
|
||||
# Table of Contents
|
||||
|
@ -100,7 +100,7 @@ figure
|
|||
Animations are defined inside `@Component` metadata. Before we can add some, we need
|
||||
to import a few animation-specific functions:
|
||||
|
||||
动画会被定义在 `@Component` 元数据中。在添加动画之前,我们得先引入一些与动画有关的函数:
|
||||
动画会被定义在`@Component`元数据中。在添加动画之前,我们得先引入一些与动画有关的函数:
|
||||
|
||||
+makeExample('animations/ts/app/hero-list-basic.component.ts', 'imports')(format=".")
|
||||
|
||||
|
@ -109,7 +109,7 @@ figure
|
|||
metadata. It has animated transitions between two states: `active` and `inactive`. When a
|
||||
hero is active, we display a the element in slightly larger size and lighter color.
|
||||
|
||||
通过这些,我们现在可以在组件元数据中定义一个名叫 `heroState` 的*动画触发器*。它在两个状态 `active` 和 `inactive` 之间进行转场。
|
||||
通过这些,我们现在可以在组件元数据中定义一个名叫`heroState`的*动画触发器*。它在两个状态`active`和`inactive`之间进行转场。
|
||||
当英雄处于激活状态时,它会把该元素显示得稍微大一点、亮一点。
|
||||
|
||||
+makeExample('animations/ts/app/hero-list-basic.component.ts', 'animationdef')(format=".")
|
||||
|
@ -120,14 +120,14 @@ figure
|
|||
animation metadata. In an upcoming release of Angular, support will be added for pulling
|
||||
the styles in from the component CSS stylesheet instead.
|
||||
|
||||
在这个例子中,我们在元数据中用内联的方式定义了动画样式(`color` 和 `transform`)。在即将到来的一个 Angular 版本中,还将支持从组件的 CSS 样式表中提取样式。
|
||||
在这个例子中,我们在元数据中用内联的方式定义了动画样式(`color`和`transform`)。在即将到来的一个Angular版本中,还将支持从组件的CSS样式表中提取样式。
|
||||
|
||||
:marked
|
||||
We now have an animation defined but it is not yet used anywhere. We can change that by
|
||||
attaching it to one or more elements in the component's template using the "`@triggerName`"
|
||||
syntax:
|
||||
|
||||
我们刚刚定义了一个动画,但它还没有被用到任何地方。要想使用它,我们可以在模板中用 `@triggerName` 语法来把它附加到一个或多个元素上。
|
||||
我们刚刚定义了一个动画,但它还没有被用到任何地方。要想使用它,我们可以在模板中用`@triggerName`语法来把它附加到一个或多个元素上。
|
||||
|
||||
+makeExample('animations/ts/app/hero-list-basic.component.ts', 'template')(format=".")
|
||||
|
||||
|
@ -137,8 +137,8 @@ figure
|
|||
attribute to the expression `hero.state`. We expect it to always be either `inactive`
|
||||
or `active`, since that's what we have defined animation states for.
|
||||
|
||||
这里,我们把该动画触发器添加到了由 `ngFor` 重复出来的每一个元素上。每个重复出来的元素都有独立的动画效果。
|
||||
我们把 `@triggerName` 属性(Attribute)的值设置成表达式 `hero.state` 。这个值应该或者是 `inactive` 或者是 `active` ,因为我们刚刚为它们俩定义过动画状态。
|
||||
这里,我们把该动画触发器添加到了由`ngFor`重复出来的每一个元素上。每个重复出来的元素都有独立的动画效果。
|
||||
我们把`@triggerName`属性(Attribute)的值设置成表达式`hero.state`。这个值应该或者是`inactive`或者是`active`,因为我们刚刚为它们俩定义过动画状态。
|
||||
|
||||
With this setup, an animated transition is shown whenever a hero object changes state!
|
||||
Here's the full component implementation:
|
||||
|
@ -155,7 +155,7 @@ figure
|
|||
Angular animations are defined in terms of logical **states** and **transitions**
|
||||
between states.
|
||||
|
||||
Angular 动画是由**状态**和**状态之间的转场效果**所定义的。
|
||||
Angular动画是由**状态**和**状态之间的转场效果**所定义的。
|
||||
|
||||
An animation state is a string value that we define in our application code. In the example
|
||||
above we used the states `'active'` and `'inactive'` based on the logical state of
|
||||
|
@ -163,7 +163,7 @@ figure
|
|||
or it can be a value computed in a method. The important thing is that we can read it into the
|
||||
component's template.
|
||||
|
||||
动画状态是一个由程序代码中定义的字符串值。在上面的例子中,我们基于英雄对象的逻辑状态使用了 `'active'` 和 `'inactive'` 这两种状态。
|
||||
动画状态是一个由程序代码中定义的字符串值。在上面的例子中,我们基于英雄对象的逻辑状态使用了`'active'`和`'inactive'`这两种状态。
|
||||
状态的来源可以是像本例中这样简单的对象属性,也可以是由方法计算出来的值。重点是,我们得能从组件模板中读取它。
|
||||
|
||||
We can define *styles* for each animation state:
|
||||
|
@ -178,7 +178,7 @@ figure
|
|||
*as long as it remains in that state*. In that sense, we are defining more than just
|
||||
animations here. We're actually defining what styles the element has in different states.
|
||||
|
||||
这些 `state` 具体定义了每个状态的*最终样式*。一旦元素转场到那个状态,该样式就会被应用到此元素上,*当它留在此状态时*,这些样式也会一直保持着。
|
||||
这些`state`具体定义了每个状态的*最终样式*。一旦元素转场到那个状态,该样式就会被应用到此元素上,*当它留在此状态时*,这些样式也会一直保持着。
|
||||
从这个意义上讲,这里我们其实并不只是在定义动画,而是在定义该元素在不同状态时应该具有的样式。
|
||||
|
||||
Once we have states, we can define *transitions* between the states. Each transition
|
||||
|
@ -195,7 +195,7 @@ figure.image-display
|
|||
If we have the same timing configuration for several transitions, we can combine
|
||||
them into the same `transition` definition:
|
||||
|
||||
如果多个转场都有同样的时间线配置,我们就可以把它们合并进同一个 `transition` 定义中:
|
||||
如果多个转场都有同样的时间线配置,我们就可以把它们合并进同一个`transition`定义中:
|
||||
|
||||
+makeExample('animations/ts/app/hero-list-combined-transitions.component.ts', 'transitions')(format=".")
|
||||
|
||||
|
@ -203,7 +203,7 @@ figure.image-display
|
|||
When we have the same timing for both directions of a transition, as we do in the previous
|
||||
example, we can use the `<=>` shorthand syntax:
|
||||
|
||||
如果我们要对同一个转场的两个方向都使用相同的时间线(就像前面的例子中那样),就可以使用 `<=>` 这种简写语法:
|
||||
如果我们要对同一个转场的两个方向都使用相同的时间线(就像前面的例子中那样),就可以使用`<=>`这种简写语法:
|
||||
|
||||
+makeExample('animations/ts/app/hero-list-twoway.component.ts', 'transitions')(format=".")
|
||||
|
||||
|
@ -214,8 +214,8 @@ figure.image-display
|
|||
When the transition finishes, none of these styles will be kept because they're not
|
||||
defined in a `state`.
|
||||
|
||||
有时我们会希望一些样式只在动画期间生效,但在结束后并不保留它们。这时我们可以把这些样式内联在 `transition` 中进行定义。
|
||||
在这个例子中,该元素会立刻获得一组样式,然后动态转场到下一个状态。当转场结束时,这些样式并不会被保留,因为它们并没有被定义在 `state` 中。
|
||||
有时我们会希望一些样式只在动画期间生效,但在结束后并不保留它们。这时我们可以把这些样式内联在`transition`中进行定义。
|
||||
在这个例子中,该元素会立刻获得一组样式,然后动态转场到下一个状态。当转场结束时,这些样式并不会被保留,因为它们并没有被定义在`state`中。
|
||||
|
||||
+makeExample('animations/ts/app/hero-list-inline-styles.component.ts', 'transitions')(format=".")
|
||||
|
||||
|
@ -231,11 +231,11 @@ figure.image-display
|
|||
|
||||
* The `active => *` transition applies when the element's state changes from `active` to anything else.
|
||||
|
||||
* 当该元素的状态从 `active` 变成任何其它状态时, `active => *` 转场都会生效。
|
||||
* 当该元素的状态从`active`变成任何其它状态时,`active => *`转场都会生效。
|
||||
|
||||
* The `* => *` transition applies when *any* change between two states takes place.
|
||||
|
||||
* 当在*任意*两个状态之间切换时, `* => *` 转场都会生效。
|
||||
* 当在*任意*两个状态之间切换时,`* => *`转场都会生效。
|
||||
|
||||
figure.image-display
|
||||
img(src="/resources/images/devguide/animations/ng_animate_transitions_inactive_active_wildcards.png" alt="The wildcard state can be used to match many different transitions at once" width="400")
|
||||
|
@ -244,20 +244,20 @@ figure.image-display
|
|||
:marked
|
||||
### The `void` state
|
||||
|
||||
### `void` 状态
|
||||
### `void`状态
|
||||
|
||||
There's one special state called `void` that may apply to any animation. It applies
|
||||
when the element is *not* attached to a view. This may be because it has not yet been
|
||||
added or because it has been removed. The `void` state is useful for defining "enter" and
|
||||
"leave" animations.
|
||||
|
||||
有一种叫做 `void` 的特殊状态,它可以应用在任何动画中。它表示元素*没有*被附加到视图。这种情况可能是由于它尚未被添加进来或者已经被移除了。
|
||||
`void` 状态在定义“进场”和“离场”的动画时会非常有用。
|
||||
有一种叫做`void`的特殊状态,它可以应用在任何动画中。它表示元素*没有*被附加到视图。这种情况可能是由于它尚未被添加进来或者已经被移除了。
|
||||
`void`状态在定义“进场”和“离场”的动画时会非常有用。
|
||||
|
||||
For example the `* => void` transition applies when the element leaves the view,
|
||||
regardless of what state it was in before it left.
|
||||
|
||||
比如当一个元素离开视图时, `* => void` 转场就会生效,而不管它在离场以前是什么状态。
|
||||
比如当一个元素离开视图时,`* => void`转场就会生效,而不管它在离场以前是什么状态。
|
||||
|
||||
figure.image-display
|
||||
img(src="/resources/images/devguide/animations/ng_animate_transitions_void_in.png" alt="The void state can be used for enter and leave transitions" width="400")
|
||||
|
@ -265,7 +265,7 @@ figure.image-display
|
|||
:marked
|
||||
The wildcard state `*` also matches `void`.
|
||||
|
||||
`*` 通配符状态也能匹配 `void` 。
|
||||
`*`通配符状态也能匹配`void`。
|
||||
|
||||
## Example: Entering and Leaving
|
||||
|
||||
|
@ -277,15 +277,15 @@ figure
|
|||
Using the `void` and `*` states we can define transitions that animate the
|
||||
entering and leaving of elements:
|
||||
|
||||
使用 `void` 和 `*` 状态,我们可以定义元素进场与离场时的转场动画:
|
||||
使用`void`和`*`状态,我们可以定义元素进场与离场时的转场动画:
|
||||
|
||||
* Enter: `void => *`
|
||||
|
||||
* 进场: `void => *`
|
||||
* 进场:`void => *`
|
||||
|
||||
* Leave: `* => void`
|
||||
|
||||
* 离场: `* => void`
|
||||
* 离场:`* => void`
|
||||
|
||||
+makeExample('animations/ts/app/hero-list-enter-leave.component.ts', 'animationdef')(format=".")
|
||||
|
||||
|
@ -295,7 +295,7 @@ figure
|
|||
we want the transforms to be different on enter and leave: The element enters from the left
|
||||
and leaves to the right.
|
||||
|
||||
注意,在这个例子中,这些样式在转场定义中被直接应用到了 `void` 状态,但并没有一个单独的 `state(void)` 定义。
|
||||
注意,在这个例子中,这些样式在转场定义中被直接应用到了`void`状态,但并没有一个单独的`state(void)`定义。
|
||||
这么做是因为我们希望在进场与离场时使用不一样的转换效果:元素从左侧进场,从右侧离开。
|
||||
|
||||
## Example: Entering and Leaving from Different States
|
||||
|
@ -315,19 +315,19 @@ figure
|
|||
|
||||
* Inactive hero enter: `void => inactive`
|
||||
|
||||
* 非激活英雄进场: `void => inactive`
|
||||
* 非激活英雄进场:`void => inactive`
|
||||
|
||||
* Active hero enter: `void => active`
|
||||
|
||||
* 激活英雄进场: `void => active`
|
||||
* 激活英雄进场:`void => active`
|
||||
|
||||
* Inactive hero leave: `inactive => void`
|
||||
|
||||
* 非激活英雄离场: `inactive => void`
|
||||
* 非激活英雄离场:`inactive => void`
|
||||
|
||||
* Active hero leave: `active => void`
|
||||
|
||||
* 激活英雄离场: `active => void`
|
||||
* 激活英雄离场:`active => void`
|
||||
|
||||
We now have fine-grained control over each transition:
|
||||
|
||||
|
@ -349,7 +349,7 @@ figure.image-display
|
|||
borders and many others. The W3C maintains
|
||||
[a list of animatable properties](https://www.w3.org/TR/css3-transitions/#animatable-properties).
|
||||
|
||||
由于 Angular 的动画支持是基于 Web Animations 标准的,所以我们也能支持浏览器认为可以*参与动画*的任何属性。这些属性包括位置(position)、大小(size)、变换(transform)、颜色(color)、边框(border)等很多属性。 W3C 维护着
|
||||
由于Angular的动画支持是基于Web Animations标准的,所以我们也能支持浏览器认为可以*参与动画*的任何属性。这些属性包括位置(position)、大小(size)、变换(transform)、颜色(color)、边框(border)等很多属性。W3C维护着
|
||||
[一个“可动”属性列表](https://www.w3.org/TR/css3-transitions/#animatable-properties)。
|
||||
|
||||
For positional properties that have a numeric value, we can define a unit by providing
|
||||
|
@ -368,7 +368,7 @@ figure.image-display
|
|||
|
||||
* `50` is the same as saying `'50px'`
|
||||
|
||||
* `50` 相当于 `'50px'`
|
||||
* `50`相当于`'50px'`
|
||||
|
||||
## Automatic Property Calculation
|
||||
|
||||
|
@ -383,13 +383,13 @@ figure
|
|||
to have widths and heights that depend on their content and the screen size. These
|
||||
properties are often tricky to animate with CSS.
|
||||
|
||||
有时候,我们想在动画中使用的尺寸类样式,它的值在开始运行之前都是不可知的。比如,元素的宽度和高度往往依赖于它们的内容和屏幕的尺寸。处理这些属性对 CSS 动画而言通常是相当棘手的。
|
||||
有时候,我们想在动画中使用的尺寸类样式,它的值在开始运行之前都是不可知的。比如,元素的宽度和高度往往依赖于它们的内容和屏幕的尺寸。处理这些属性对CSS动画而言通常是相当棘手的。
|
||||
|
||||
With Angular we can use a special `*` property value in these cases. What it means
|
||||
is that the value of this property will be computed at runtime and then plugged into
|
||||
the animation.
|
||||
|
||||
如果用 Angular 动画,我们就可以用一个特殊的 `*` 属性值来处理这种情况。该属性的值将会在运行期被计算出来,然后插入到这个动画中。
|
||||
如果用Angular动画,我们就可以用一个特殊的`*`属性值来处理这种情况。该属性的值将会在运行期被计算出来,然后插入到这个动画中。
|
||||
|
||||
The "leave" animation in this example takes whatever height the element has before it
|
||||
leaves and animates from that height to zero:
|
||||
|
@ -420,15 +420,15 @@ figure
|
|||
|
||||
* As a plain number, in milliseconds: `100`
|
||||
|
||||
* 作为一个普通数字,以毫秒为单位,如: `100`
|
||||
* 作为一个普通数字,以毫秒为单位,如:`100`
|
||||
|
||||
* In a string, as milliseconds: `'100ms'`
|
||||
|
||||
* 作为一个字符串,以毫秒为单位,如: `'100ms'`
|
||||
* 作为一个字符串,以毫秒为单位,如:`'100ms'`
|
||||
|
||||
* In a string, as seconds: `'0.1s'`
|
||||
|
||||
* 作为一个字符串,以秒为单位,如: `'0.1s'`
|
||||
* 作为一个字符串,以秒为单位,如:`'0.1s'`
|
||||
|
||||
### Delay
|
||||
|
||||
|
@ -442,7 +442,7 @@ figure
|
|||
|
||||
* Wait for 100ms and then run for 200ms: `'0.2s 100ms'`
|
||||
|
||||
* 等待100毫秒,然后运行200毫秒: `'0.2s 100ms'` 。
|
||||
* 等待100毫秒,然后运行200毫秒:`'0.2s 100ms'`。
|
||||
|
||||
### Easing
|
||||
|
||||
|
@ -454,15 +454,15 @@ figure
|
|||
can control the easing by adding it as a *third* value in the string after the duration
|
||||
and the delay (or as the *second* value when there is no delay):
|
||||
|
||||
[缓动函数](http://easings.net/)用于控制动画在运行期间如何加速和减速。比如:使用 `ease-in` 函数意味着动画开始时相对缓慢,然后在进行中逐步加速。我们可以通过在这个字符串中的持续时间和延迟后面添加*第三个*值来控制使用哪个缓动函数(如果没有定义延迟就作为*第二个*值)。
|
||||
[缓动函数](http://easings.net/)用于控制动画在运行期间如何加速和减速。比如:使用`ease-in`函数意味着动画开始时相对缓慢,然后在进行中逐步加速。我们可以通过在这个字符串中的持续时间和延迟后面添加*第三个*值来控制使用哪个缓动函数(如果没有定义延迟就作为*第二个*值)。
|
||||
|
||||
* Wait for 100ms and then run for 200ms, with easing: `'0.2s 100ms ease-out'`
|
||||
|
||||
* 等待100毫秒,然后运行200毫秒,并且带缓动: `'0.2s 100ms ease-out'`
|
||||
* 等待100毫秒,然后运行200毫秒,并且带缓动:`'0.2s 100ms ease-out'`
|
||||
|
||||
* Run for 200ms, with easing: `'0.2s ease-in-out'`
|
||||
|
||||
* 运行200毫秒,并且带缓动: `'0.2s ease-in-out'`
|
||||
* 运行200毫秒,并且带缓动:`'0.2s ease-in-out'`
|
||||
|
||||
figure
|
||||
img(src="/resources/images/devguide/animations/animation_timings.gif" alt="Animations with specific timings" align="right" style="width:220px;margin-left:20px" )
|
||||
|
@ -513,7 +513,7 @@ figure
|
|||
measures from 0 to 1. The final timeline of the animation will based on the combination
|
||||
of keyframe offsets, duration, delay, and easing.
|
||||
|
||||
注意,这个偏移量并*不是*用绝对数字定义的时间段,而是在 0 到 1 之间的相对值(百分比)。动画的最终时间线会基于关键帧的偏移量、持续时间、延迟和缓动函数计算出来。
|
||||
注意,这个偏移量并*不是*用绝对数字定义的时间段,而是在0到1之间的相对值(百分比)。动画的最终时间线会基于关键帧的偏移量、持续时间、延迟和缓动函数计算出来。
|
||||
|
||||
Defining offsets for keyframes is optional. If we omit them, offsets with even
|
||||
spacing are automatically assigned. For example, three keyframes without predefined
|
||||
|
@ -533,13 +533,13 @@ figure
|
|||
We've already seen how we can animate multiple style properties at the same time:
|
||||
Just put all of them into the same `style()` definition!
|
||||
|
||||
我们已经知道该如何在同一时间段进行多个样式的动画了:只要把它们都放进同一个 `style()` 定义中就行了!
|
||||
我们已经知道该如何在同一时间段进行多个样式的动画了:只要把它们都放进同一个`style()`定义中就行了!
|
||||
|
||||
But we may also want to configure different *timings* for animations that happen
|
||||
in parallel. For example, we may want to animate two CSS properties but use a
|
||||
different easing function for each one.
|
||||
|
||||
但我们也可能会希望为同时发生的几个动画配置不同的*时间线*。比如,我们可能希望同时对两个 CSS 属性做动画,但又得为它们定义不同的缓动函数。
|
||||
但我们也可能会希望为同时发生的几个动画配置不同的*时间线*。比如,我们可能希望同时对两个CSS属性做动画,但又得为它们定义不同的缓动函数。
|
||||
|
||||
For this we can use animation *groups*. In this example we use groups both on
|
||||
enter and leave so that we can use two different timing configurations. Both
|
||||
|
@ -553,4 +553,4 @@ figure
|
|||
:marked
|
||||
One group animates the element transform and width. The other animates the opacity.
|
||||
|
||||
其中一个动画组对元素的 `transform` 和 `width` 做动画,另一个组则对 `opacity` 做动画。
|
||||
其中一个动画组对元素的`transform`和`width`做动画,另一个组则对`opacity`做动画。
|
||||
|
|
|
@ -16,6 +16,10 @@ td, th {
|
|||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
code, [lang=english] {
|
||||
margin-left: 0.2em;
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
}
|
||||
|
||||
.about-cn-translation {
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
// TODO: refactor me!
|
||||
var sourceVisible = localStorage.getItem('source-visible') === 'true';
|
||||
|
||||
(function ($) {
|
||||
var nodes = document.querySelectorAll('p, li, h1, h2, h3, h4, h5, h6, header, a, button, small');
|
||||
_.each(nodes, function (node) {
|
||||
var $node = $(node);
|
||||
|
||||
if (isLink(node) || isButton(node)) {
|
||||
$node.on('click', function (event) {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
if (/^http?s:\/\//.test($node.attr('href')) && !$node.attr('target')) {
|
||||
$node.attr('target', '_blank');
|
||||
}
|
||||
}
|
||||
|
||||
var prevNode = node.previousElementSibling;
|
||||
var $prevNode = $(prevNode);
|
||||
|
||||
if (!prevNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTranslationResult(node, prevNode)) {
|
||||
if ($prevNode.hasClass('nav-list-item')) {
|
||||
return;
|
||||
}
|
||||
if (isPureEnglish($node.text()) && $node.text() !== $prevNode.text()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPureEnglish($prevNode.text())) {
|
||||
$node.attr('id', prevNode.id);
|
||||
$node.addClass('translated');
|
||||
$node.addClass('translated-cn');
|
||||
$prevNode.removeAttr('id');
|
||||
$prevNode.addClass('original-english');
|
||||
if (!sourceVisible) {
|
||||
$prevNode.addClass('hidden');
|
||||
}
|
||||
if (!isLink(node) && !isButton(node)) {
|
||||
$node.on('click', function () {
|
||||
$prevNode.toggleClass('hidden');
|
||||
});
|
||||
$prevNode.on('click', function () {
|
||||
$prevNode.addClass('hidden');
|
||||
});
|
||||
}
|
||||
$node.after($prevNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function isLink(node) {
|
||||
return node.tagName.toUpperCase() === 'A';
|
||||
}
|
||||
|
||||
function isButton(node) {
|
||||
return node.tagName.toUpperCase() === 'BUTTON';
|
||||
}
|
||||
|
||||
function isPureEnglish(text) {
|
||||
// accept — , quotes, ® and façade too.
|
||||
return /^[\1-\255—’“”ç®…]*$/.test(text);
|
||||
}
|
||||
|
||||
function attributesToString(node) {
|
||||
return _.chain(node.attributes)
|
||||
.map(function (value) {
|
||||
if (value.name === 'id') {
|
||||
return '';
|
||||
} else {
|
||||
return value.name + '=' + value.value;
|
||||
}
|
||||
})
|
||||
.sortBy()
|
||||
.value()
|
||||
.join(';');
|
||||
}
|
||||
|
||||
function isClonedNode(node1, node2) {
|
||||
return node1.tagName === node2.tagName &&
|
||||
attributesToString(node1) === attributesToString(node2);
|
||||
}
|
||||
|
||||
function indexOfSameType(node) {
|
||||
var i = 0;
|
||||
var aNode = node.parentNode.firstChild;
|
||||
while (aNode !== node) {
|
||||
++i;
|
||||
if (aNode.tagName !== node.tagName) {
|
||||
i = 0;
|
||||
}
|
||||
aNode = aNode.nextElementSibling;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
function isTranslationResult(node, prevNode) {
|
||||
return indexOfSameType(node) % 2 === 1 && isClonedNode(node, prevNode) && isPureEnglish(prevNode.innerText);
|
||||
}
|
||||
})(angular.element);
|
|
@ -50,7 +50,6 @@
|
|||
|
||||
- Joeylin
|
||||
- 张旋
|
||||
- Hantsy
|
||||
- 还有一些做好事不留名的雷锋
|
||||
|
||||
想让你的名字也出现在这里吗?请提供[反馈、纠错](https://github.com/angular/angular-cn/issues)。
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
// TODO: refactor me!
|
||||
var sourceVisible = localStorage.getItem('source-visible') === 'true';
|
||||
|
||||
(function ($) {
|
||||
addOriginalToggler();
|
||||
addSpacingBetweenCnAndEn();
|
||||
|
||||
function addOriginalToggler() {
|
||||
var nodes = document.querySelectorAll('p, li, h1, h2, h3, h4, h5, h6, header, a, button, small');
|
||||
_.each(nodes, function (node) {
|
||||
var $node = $(node);
|
||||
|
||||
if (isLink(node) || isButton(node)) {
|
||||
$node.on('click', function (event) {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
if (/^http?s:\/\//.test($node.attr('href')) && !$node.attr('target')) {
|
||||
$node.attr('target', '_blank');
|
||||
}
|
||||
}
|
||||
|
||||
var prevNode = node.previousElementSibling;
|
||||
var $prevNode = $(prevNode);
|
||||
|
||||
if (!prevNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTranslationResult(node, prevNode)) {
|
||||
if ($prevNode.hasClass('nav-list-item')) {
|
||||
return;
|
||||
}
|
||||
if (isPureEnglish($node.text()) && $node.text() !== $prevNode.text()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPureEnglish($prevNode.text())) {
|
||||
$node.attr('id', prevNode.id);
|
||||
$node.addClass('translated');
|
||||
$node.addClass('translated-cn');
|
||||
$prevNode.removeAttr('id');
|
||||
$prevNode.addClass('original-english');
|
||||
if (!sourceVisible) {
|
||||
$prevNode.addClass('hidden');
|
||||
}
|
||||
if (!isLink(node) && !isButton(node)) {
|
||||
$node.on('click', function () {
|
||||
$prevNode.toggleClass('hidden');
|
||||
});
|
||||
$prevNode.on('click', function () {
|
||||
$prevNode.addClass('hidden');
|
||||
});
|
||||
}
|
||||
$node.after($prevNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function addSpacingBetweenCnAndEn($node) {
|
||||
var nodes = document.querySelectorAll('.translated-cn');
|
||||
_.each(nodes, function (node) {
|
||||
var text = node.innerHTML;
|
||||
text = text.replace(/([\x20-\xff]+)/g, '<span lang="english">$1</span>');
|
||||
node.innerHTML = text;
|
||||
});
|
||||
}
|
||||
|
||||
function isLink(node) {
|
||||
return node.tagName.toUpperCase() === 'A';
|
||||
}
|
||||
|
||||
function isButton(node) {
|
||||
return node.tagName.toUpperCase() === 'BUTTON';
|
||||
}
|
||||
|
||||
function isPureEnglish(text) {
|
||||
// accept — , quotes, ® and façade too.
|
||||
return /^[\1-\255—’“”ç®…]*$/.test(text);
|
||||
}
|
||||
|
||||
function attributesToString(node) {
|
||||
return _.chain(node.attributes)
|
||||
.map(function (value) {
|
||||
if (value.name === 'id') {
|
||||
return '';
|
||||
} else {
|
||||
return value.name + '=' + value.value;
|
||||
}
|
||||
})
|
||||
.sortBy()
|
||||
.value()
|
||||
.join(';');
|
||||
}
|
||||
|
||||
function isClonedNode(node1, node2) {
|
||||
return node1.tagName === node2.tagName &&
|
||||
attributesToString(node1) === attributesToString(node2);
|
||||
}
|
||||
|
||||
function indexOfSameType(node) {
|
||||
var i = 0;
|
||||
var aNode = node.parentNode.firstChild;
|
||||
while (aNode !== node) {
|
||||
++i;
|
||||
if (aNode.tagName !== node.tagName) {
|
||||
i = 0;
|
||||
}
|
||||
aNode = aNode.nextElementSibling;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
function isTranslationResult(node, prevNode) {
|
||||
return indexOfSameType(node) % 2 === 1 && isClonedNode(node, prevNode) && isPureEnglish(prevNode.innerText);
|
||||
}
|
||||
})(angular.element);
|
Loading…
Reference in New Issue