这些都离不开一个术语叫

说说大家都如数家珍的网页动画技艺

2015/12/07 · CSS,
HTML5,
JavaScript · 1
评论 ·
动画

初稿出处:
大搜车的前面端团队博客   

前言

从远古手绘翻书动画,到胶片电影,再到多张永琛态图合成 gif,
这几个都离不开一个术语叫

也正是大家须求绘制每一帧,然后决定一下帧与帧之间的时日距离。

但是相邻两帧之间的转移并十分小,重复绘制浪费体力,
好在Computer代码能够复制粘贴,然后修改一下更改的地点就能够了。

等等,好像何地不对。

Computer代码除了能够复制粘贴,还会有抽象才能。
咱俩得以把须求复制粘贴的代码交给Computer来再度施行。
把必要转移的地点,交给计算机来运算。

而网页中有所运算本领的只有JS,别的的就只好是概念一下参数,剩下的就交给浏览器了。

那就是 JS 算编制程序,而 HTML、css 不算编程的由来。
连带商讨,回复内容+关键字#你丫才码农#

开始

网页动画能够经过以下三种办法贯彻(gif、flash 除却),

小编知识面有限,如有遗漏,请留言公告本人。
连锁商讨,回复内容+关键字#网页动画实现方式#

  • css3 动画
  • SVG 动画
  • JS 动画(包罗 css、SVG 的习性修改达成的卡通片)

小编以为 canvas、webGL 只可以算是一种绘图方式。
他们的动画片也都以经过 JS 修改参数来落到实处的。
连锁探讨,回复内容+关键字#canvas动画#

最早 JS 通过 setTimeout() 或者 setInterval() 方法设置二个时日,
来调整帧与帧之间的日子距离。

  • setTimeout() 直接用跳出来终止下一帧。
  • setInterval() 使用 clearInterval() 来撤销周期实行。

但是如此效果说不定相当不够流畅,且会占有额外的能源。
连带探究,回复内容+关键字#你ST设置几毫秒#
参考:

新兴,有了一个requestAnimationFrame(),让浏览器决定最优帧速率选择绘制下一帧的最佳时机
requestAnimationFrame()cancelAnimationFrame() 来结束。

为此大家来改动一下心想方法,既然帧与帧之间的小时距离不用想念了,那就关怀一下变化速率吧。

  • Partial support refers to lacking cancelAnimationFrame support.
  • Supports webkitCancelRequestAnimationFrame rather than
    `webkitCancelAnimationFrame.

— caniuse.com

好了,动画讲完了,你去找个科目看《canvas 绘图》?

别介,这才刚刚先河。

慢慢的,大家开采部分轻便易行动画只是在改换几个 css
属性,并且只是在两七个状态之间来回转变。
恢宏的体力却疏落在多少个情景间的补间状态函数上,并且质量犬牙相错。

来来来,这种事情就提交浏览器嘛。

css3 动画

能够施行补间状态的尺度是,属性值能够转变来数值,那样就会加入运算。如:

  • 颜色(color,background-color,border-color…)
  • 长度/大小(width,height,font-size,border-width,border-radius…)
  • 透明度(opacity)
  • 堆放顺序(z-index)你吖补间它有毛用

而不能够加入运算就意味着无法拿来补间状态,也正是未有中间状态,如:

  • position(absolute、fixed、relative…)
  • background-image(多少个规定的 url)

一拍脑门就能够体会精通,创制三个补间动画的口径有:

  • 始于情状
  • 终止状态
  • 这些都离不开一个术语叫。实施时间
  • 补间效果

固然有个方块,宽度从 10px 形成 100px。

伊始情形呢,在原 css 里就足以定义了 width: 10px

终结状态吧,大家能够通过用 JS 直接修改 width 值,大概增添贰个 class
选拔器的不二诀要,
或者是 :hover 等任何代表处境的伪类,让 width: 100px

而那时候,你需求叁个补间动画属性来注明 执行时间补间效果
它就是 transition,普通话译作 过渡,正是自己所说的补间的情趣。

transition 为以下属性的简写

  • transition-property 规定哪个属性应用过渡
  • transition-duration 执行时间
  • transition-timing-function 补间效果,默认为 ease
  • transition-delay 延迟多少时间开始

这些都离不开一个术语叫。这些都离不开一个术语叫。参考:

Support listed is for transition properties as well as the
transitionend event. The prefixed name in WebKit browsers is
webkitTransitionEnd

— caniuse.com

这些都离不开一个术语叫。css3 还提供了叁个 animation 属性来创制更增加的自定义动画,而收缩 JS
的涉企。

比如:

  • 这些都离不开一个术语叫。您想贰个动画中持有七个情景
  • 各类景况修改的属性值比较多
  • 巡回播放
  • 逆向播放
  • 可活动开首,可中途抛锚

animation@keyframes 合营使用。

@keyframes 用来定义动画,animation 则能够多处选用,他们经过叁个 name
来三番五次互相,
因此 @keyframes 要求求起个名字,而 animation 则有个
animation-name

animation 在利用时,你能够自定义它:

  • animation-duration 执行时间
  • animation-time-function 补间效果,默认是 ease
  • animation-delay 延迟多少时间开始
  • animation-iteration-count 循环播放次数
  • animation-direction 是否在下一周期逆向播放
  • animation-play-state
    动画是否暂停,通过它,可以实现是否自动播放。要中途暂停的话,就要修改值,通过伪类或 JS 实现
  • animation-fill-mode 那个性格倒是有一些出乎意想不到,请自行钻研利用境况

可见 w3c
标准制定者们思考到大家要用起来轻巧吗,基本上和大家寻思格局同样。

这些都离不开一个术语叫。兑现动画的四个情景是在 @keyframes 定义时完结的。

采用 0%~100% 的细分格局,我们就无须在 执行时间 之外思考时间难点了。

参考:

Partial support in Android browser refers to buggy behavior in
different scenarios.

–caniuse.com

SVG 动画

css3 动画属性只管得住自身的 css 属性,SVG 绘制的图样,还得 SVG
本身消除。而对此 SVG 的 css 样式,一般二种皆可。

SVG 大大们的观念方法就有一点绕了,竟然提供了 5 种动画 标签让我选用:

  • set 相当于 animate 的 calcMode="discrete",忽略
  • animate
  • animateColor 相当于 animate 的 attributeName="color",忽略
  • animateTransform
  • animateMotion

我们先来探视和 css3 最像的 animate 标签,具有的属性有

  • attributeName 规定哪个属性应用过渡
  • from 开始状态
  • to/by 结束状态,至少出现一个
  • values 多个状态时,忽略 from/to/by
  • begin 延迟多少时间开始
  • dur 执行时间
  • calcMode,keyTimes,keySplines 自定义补间效果
  • repeatCount,repeatDur 循环播放次数/持续时间

额,大约便是这么,下多个吧。

animateTransform 首假使为着 attributeName="transform"
跟 css3 动画组成 transform 转变类似,多了二个 type="scale"
属性用来分歧相关参数。

animateMotion 是 SVG 甩 css3
动画一条街的雄强本事,能够让SVG各类图片沿着一定的 path 路线运动。

SVG 动画比 css 动画更加强硬,所以也更复杂。

细分成那 5
类标签,大约是性质思虑,人工轻易区分一下数值、颜色、调换,可以为计算机省去大批量的失效运算。

小编在那边也不能够讲的更详尽,估算你也没看太驾驭
建议阅读:

JS 还大概有吗用

透过表明属性,调用浏览器来落到实处的章程,终归有限,JS
可以为我们提供最棒大概。

因此对照 CSS3 和 SVG
大家也能看出来,要促成的事物越来越多,大家必要区分、记念的性质也愈来愈多。
多个长短不一动画使用评释属性的法门有希望并不曾经过编写制定逻辑来得更加爽。看,SVG.js。

在此地倒是想到了 Grunt 和 Gulp 之争
连锁商量,请过来+关键字#不要给我太多配置项#

css3 属性中扬言的补间效果其实有限,SVG 的 calcMode,keyTimes,keySplines
又略显复杂,
于是乎 github 上出现了一大批判补间效果仓库,更有庞大者弥补了 CSS3 与 SVG
动画上各种方面包车型地铁不足。

  • 轻巧易行小巧,使用简便
  • 4 大类/29 种补间动画效果
  • 支持 SVG path 路线的补间过渡
    • !稍微有一些鸡肋,path 长度不等同或项目区别偶然候出现动画混乱
  • !仅帮助伊始、结束多个情景
animate({ el: "div", // 选择器 duration: 1000, // 执行时间 delay: 0,
// 延迟多少时间开始 easing: "easeOutElastic", // 补间效果 loop:
false, // 是否循环 direction: normal, // 是否重复 begin: function ()
{}, // 开始事件 complete: function () {}, // 结束事件 ...: \['',
''\] // css/SVG 需要改变的属性 });

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d2831927818175163-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831927818175163-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831927818175163-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831927818175163-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831927818175163-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831927818175163-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831927818175163-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831927818175163-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831927818175163-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831927818175163-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831927818175163-11">
11
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d2831927818175163-1" class="crayon-line">
animate({
</div>
<div id="crayon-5b8f6d2831927818175163-2" class="crayon-line crayon-striped-line">
    el: &quot;div&quot;,  // 选择器
</div>
<div id="crayon-5b8f6d2831927818175163-3" class="crayon-line">
    duration: 1000, // 执行时间
</div>
<div id="crayon-5b8f6d2831927818175163-4" class="crayon-line crayon-striped-line">
    delay: 0,   // 延迟多少时间开始
</div>
<div id="crayon-5b8f6d2831927818175163-5" class="crayon-line">
    easing: &quot;easeOutElastic&quot;,   // 补间效果
</div>
<div id="crayon-5b8f6d2831927818175163-6" class="crayon-line crayon-striped-line">
    loop: false,    // 是否循环
</div>
<div id="crayon-5b8f6d2831927818175163-7" class="crayon-line">
    direction: normal,  // 是否重复
</div>
<div id="crayon-5b8f6d2831927818175163-8" class="crayon-line crayon-striped-line">
    begin: function () {},  // 开始事件
</div>
<div id="crayon-5b8f6d2831927818175163-9" class="crayon-line">
    complete: function () {},   // 结束事件
</div>
<div id="crayon-5b8f6d2831927818175163-10" class="crayon-line crayon-striped-line">
    ...: ['', '']   // css/SVG 需要改变的属性
</div>
<div id="crayon-5b8f6d2831927818175163-11" class="crayon-line">
});
</div>
</div></td>
</tr>
</tbody>
</table>

无论你定义多少补间效果,都满意不断全数人的急需,这里有个 path
路线补间函数生成器。
var myFunc = mojs.easing.path(path),输入三个 SVG path,myFunc()
正是你谐和的补间函数。

  • 太屌,不举办反面商量
  • 最欣赏它的链式操作
var svg = d3.select("\#a") // 选择器 .attr('d',
svg\_num\_path\_d\[0\]) // ... 可以进行其他设置 .attr('fill',
'\#f00') // 设置初始状态 .transition() // 返回 transition 对象
.call(function (transition) { return transition // 承接 transition
对象 .duration(3000) // 执行时间 .delay(0) // 延迟多少时间开始
.ease('cubic-in-out') // 补间效果 .attr('fill', '\#ff0'); //
本次过渡结束状态 }) // 重新返回选择器对象 // ... 可以进行其他设置
.transition() // 进行下一个过渡 .call(function (transition) { return
transition.duration(3000).attr('fill', '\#f0f'); }) // ...
可以进行其他设置 ;

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d2831931570115466-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831931570115466-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831931570115466-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831931570115466-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831931570115466-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831931570115466-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831931570115466-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831931570115466-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831931570115466-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831931570115466-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831931570115466-11">
11
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831931570115466-12">
12
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831931570115466-13">
13
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831931570115466-14">
14
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831931570115466-15">
15
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831931570115466-16">
16
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831931570115466-17">
17
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831931570115466-18">
18
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831931570115466-19">
19
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d2831931570115466-1" class="crayon-line">
var svg = d3.select(&quot;#a&quot;)   // 选择器
</div>
<div id="crayon-5b8f6d2831931570115466-2" class="crayon-line crayon-striped-line">
    .attr('d', svg_num_path_d[0])
</div>
<div id="crayon-5b8f6d2831931570115466-3" class="crayon-line">
    // ... 可以进行其他设置
</div>
<div id="crayon-5b8f6d2831931570115466-4" class="crayon-line crayon-striped-line">
    .attr('fill', '#f00')   // 设置初始状态
</div>
<div id="crayon-5b8f6d2831931570115466-5" class="crayon-line">
    .transition()   // 返回 transition 对象
</div>
<div id="crayon-5b8f6d2831931570115466-6" class="crayon-line crayon-striped-line">
    .call(function (transition) {
</div>
<div id="crayon-5b8f6d2831931570115466-7" class="crayon-line">
        return transition   // 承接 transition 对象
</div>
<div id="crayon-5b8f6d2831931570115466-8" class="crayon-line crayon-striped-line">
            .duration(3000) // 执行时间
</div>
<div id="crayon-5b8f6d2831931570115466-9" class="crayon-line">
            .delay(0)   // 延迟多少时间开始
</div>
<div id="crayon-5b8f6d2831931570115466-10" class="crayon-line crayon-striped-line">
            .ease('cubic-in-out')   // 补间效果
</div>
<div id="crayon-5b8f6d2831931570115466-11" class="crayon-line">
            .attr('fill', '#ff0');  // 本次过渡结束状态
</div>
<div id="crayon-5b8f6d2831931570115466-12" class="crayon-line crayon-striped-line">
    })  // 重新返回选择器对象
</div>
<div id="crayon-5b8f6d2831931570115466-13" class="crayon-line">
    // ... 可以进行其他设置
</div>
<div id="crayon-5b8f6d2831931570115466-14" class="crayon-line crayon-striped-line">
    .transition()   // 进行下一个过渡
</div>
<div id="crayon-5b8f6d2831931570115466-15" class="crayon-line">
    .call(function (transition) {
</div>
<div id="crayon-5b8f6d2831931570115466-16" class="crayon-line crayon-striped-line">
        return transition.duration(3000).attr('fill', '#f0f');
</div>
<div id="crayon-5b8f6d2831931570115466-17" class="crayon-line">
    })
</div>
<div id="crayon-5b8f6d2831931570115466-18" class="crayon-line crayon-striped-line">
    // ... 可以进行其他设置
</div>
<div id="crayon-5b8f6d2831931570115466-19" class="crayon-line">
    ;
</div>
</div></td>
</tr>
</tbody>
</table>

  • 一个和 animateplus 同样容命理术数的框架
  • !差不离是因为主打物理引擎(未有色金属切磋所究,测度是如此),动画效果有一点点鸡肋
    • 取名极红啊,可是并从未什么样卵用
  • 也提供了重重补间效果,还援救 new ui.Easing(x, y, x, y)
    自定义补间效果

    • !自定义补间仅仅是二个简练贝塞尔曲线,和 mojspath-easing
      完全未有可比性啊
  • !多情况的连通是 promise 的写法,完全未有 d3.js 的链式操作来的爽
// 选择器,以及初始状态 var ballActor = new ui.Actor({ element:
'\#ball', values: { backgroundColor: '\#ff2420', borderRadius: '50%'
} }); var morphAnimation = new ui.Tween({ values: { backgroundColor:
'\#2983ff', borderRadius: '0%', x: 300 }, // 结束状态 duration:
1000, // 执行时间 yoyo: true // 相当于 animateplus 的
direction,好奇怪的命名 // flip // loop //
onStart、onFrame、onUpdate、onComplete });
ballActor.start(morphAnimation); // 触发动画

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-11">
11
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-12">
12
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-13">
13
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-14">
14
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-15">
15
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-16">
16
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-17">
17
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-18">
18
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-19">
19
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-20">
20
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-21">
21
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2831936754356035-22">
22
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2831936754356035-23">
23
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d2831936754356035-1" class="crayon-line">
// 选择器,以及初始状态
</div>
<div id="crayon-5b8f6d2831936754356035-2" class="crayon-line crayon-striped-line">
var ballActor = new ui.Actor({
</div>
<div id="crayon-5b8f6d2831936754356035-3" class="crayon-line">
    element: '#ball',
</div>
<div id="crayon-5b8f6d2831936754356035-4" class="crayon-line crayon-striped-line">
    values: {
</div>
<div id="crayon-5b8f6d2831936754356035-5" class="crayon-line">
        backgroundColor: '#ff2420',
</div>
<div id="crayon-5b8f6d2831936754356035-6" class="crayon-line crayon-striped-line">
        borderRadius: '50%'
</div>
<div id="crayon-5b8f6d2831936754356035-7" class="crayon-line">
    }
</div>
<div id="crayon-5b8f6d2831936754356035-8" class="crayon-line crayon-striped-line">
});
</div>
<div id="crayon-5b8f6d2831936754356035-9" class="crayon-line">
 
</div>
<div id="crayon-5b8f6d2831936754356035-10" class="crayon-line crayon-striped-line">
var morphAnimation = new ui.Tween({
</div>
<div id="crayon-5b8f6d2831936754356035-11" class="crayon-line">
    values: {
</div>
<div id="crayon-5b8f6d2831936754356035-12" class="crayon-line crayon-striped-line">
        backgroundColor: '#2983ff',
</div>
<div id="crayon-5b8f6d2831936754356035-13" class="crayon-line">
        borderRadius: '0%',
</div>
<div id="crayon-5b8f6d2831936754356035-14" class="crayon-line crayon-striped-line">
        x: 300
</div>
<div id="crayon-5b8f6d2831936754356035-15" class="crayon-line">
    },  // 结束状态
</div>
<div id="crayon-5b8f6d2831936754356035-16" class="crayon-line crayon-striped-line">
    duration: 1000, // 执行时间
</div>
<div id="crayon-5b8f6d2831936754356035-17" class="crayon-line">
    yoyo: true  // 相当于 animateplus 的 direction,好奇怪的命名
</div>
<div id="crayon-5b8f6d2831936754356035-18" class="crayon-line crayon-striped-line">
    // flip
</div>
<div id="crayon-5b8f6d2831936754356035-19" class="crayon-line">
    // loop
</div>
<div id="crayon-5b8f6d2831936754356035-20" class="crayon-line crayon-striped-line">
    // onStart、onFrame、onUpdate、onComplete
</div>
<div id="crayon-5b8f6d2831936754356035-21" class="crayon-line">
});
</div>
<div id="crayon-5b8f6d2831936754356035-22" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6d2831936754356035-23" class="crayon-line">
ballActor.start(morphAnimation);    // 触发动画
</div>
</div></td>
</tr>
</tbody>
</table>

小编将会在此间相比较越来越多 JS 动画函数库的行使办法

鸣谢

  • 1 赞 5 收藏 1
    评论

图片 1

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图