Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

js拖放功能的实现

发表于 2020-09-03 | 更新于 2020-10-01

拖放是网页中一种很常见的交互手段。下面简单介绍使用js实现拖放功能的方法。

拖放流程

拖放元素的流程如下:

选中元素—>拖动元素—>释放元素

下面介绍上述拖放元素流程的具体实现方法。

选中元素

在HTML5标准中,为了使元素可拖动,把draggable属性设置为true。文本、图片和链接是默认可以拖放的,它们的draggable属性自动被设置成了true。图片和链接按住鼠标左键选中,就可以拖放。文本只有在被选中的情况下才能拖放。如果显示设置文本的draggable属性为true,按住鼠标左键也可以直接拖放。

draggable属性:设置元素是否可拖动。语法:

1
<element draggable="true | false | auto" >

其中:

  • true: 可以拖动
  • false: 禁止拖动
  • auto: 跟随浏览器定义是否可以拖动

拖动元素

每一个可拖动的元素,在拖动过程中,都会经历三个过程,拖动开始–>拖动过程中–> 拖动结束。

针对对象 事件名称 说明
被拖动的元素 dragstart 在元素开始被拖动时候触发
drag 在元素被拖动时反复触发
dragend 在拖动操作完成时触发
目的地对象 dragenter 当被拖动元素进入目的地元素所占据的屏幕空间时触发
dragover 当被拖动元素在目的地元素内时触发
dragleave 当被拖动元素没有放下就离开目的地元素时触发

释放

到达目的地之后,释放元素事件

针对对象 事件名称 说明
目的地对象 drop 当被拖动元素在目的地元素里放下时触发,一般需要取消浏览器的默认行为。

DataTransfer对象

与拖放操作所触发的事件同时派发的对象是DragEvent,它派生于MouseEvent,具有Event与MouseEvent对象的所有功能,并增加了dataTransfer属性。该属性用于保存拖放的数据和交互信息,返回DataTransfer对象。

DataTransfer对象常用的属性和方法如下:

属性 说明
types 只读属性。它返回一个我们在dragstart事件中设置的拖动数据格式的数组。 格式顺序与拖动操作中包含的数据顺序相同。IE10+、Edge、safari3.1、Firefox3.5+ 和Chrome4以上支持该属性
files 返回拖动操作中的文件列表。包含一个在数据传输上所有可用的本地文件列表。如果拖动操作不涉及拖动文件,此属性是一个空列表。
dropEffect 获取当前选定的拖放操作的类型或将操作设置为新类型。它应该始终设置成effectAllowed的可能值之一【none、move、copy、link】。dragover事件处理程序中针对放置目标来设置dropEffect。
effectAllowed 指定拖放操作所允许的效果。必须是其中之一【 none, copy, copyLink, copyMove, link, linkMove, move, all, uninitialized】默认为uninitialized 表示允许所有的效果。ondragstart处理程序中设置effectAllowed属性
方法 说明
void setData(format, data) 将拖动操作的拖动数据设置为指定的数据和类型。format可以是MIME类型
String getData(format) 返回指定格式的数据,format与setData()中一致
void clearData([format]) 删除给定类型的拖动操作的数据。如果给定类型的数据不存在,此方法不执行任何操作。如果不给定参数,则删除所有类型的数据。
void setDragImage(img, xOffset, yOffset) 指定一副图像,当拖动发生时,显示在光标下方。大多数情况下不用设置,因为被拖动的节点被创建成默认图片。x,y参数分别指示图像的水平、垂直偏移量

浏览器文件拖拽示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
document.addEventListener("dragenter",function(e) {
e.preventDefault();
e.stopPropagation();
},false);

document.addEventListener("dragover",function(e) {
e.preventDefault();
e.stopPropagation();
},false);

document.addEventListener("dragleave",function(e) {
e.preventDefault();
e.stopPropagation();
},false);

document.addEventListener("drop",function(e) {
e.preventDefault();
e.stopPropagation();

var df = e.dataTransfer;
var dropFiles=[];

if (df.items !==undefined){
for(var i=0;i<df.items.length;i++){
var item= df.items[i];
if(item.kind==="file" && item.getAsEntry().isFile){
var file =item.getAsFile();
dropFiles.push(file);
}
}
}
},false);

参考链接

  1. js控制文件拖拽,获取拖拽内容。,by segmentfault.
  2. HTML5原生拖拽/拖放 Drag & Drop 详解,by weiqinl.
  3. 原生JS快速实现拖放(drag and drop)效果,by MudOnTire.

Simulink模块参数在线修改方法

发表于 2020-08-14 | 更新于 2021-05-19

Simulink在建立系统模型方面非常的便捷,利用其提供的各种已封装好的组件,可以很快地构建各种模型,如飞机、导弹、诱饵弹等。但是在将导弹、诱饵弹装配到飞机上时就比较复杂了。例如,在飞机发射导弹时,如何将飞机的速度、位姿状态传递给导弹模型就是一个难题。为解决该难题,Simulink必须能够在线修改模型的参数。幸运的是,尽管比较艰难,通过一些特殊的技巧,Simulink还是能够实现在线修改模型参数的。具体的解决方案如下:

  • 模型实例化问题。以飞机携带多枚导弹为例,因为飞机携带导弹数量有限,可以直接生成多个导弹模块。如果数量实在太多,可以考虑for each subsystem。

  • 在线修改模型参数问题。利用Simulink的s函数,在Update函数中使用set_param函数修改模型参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Update(block)
decoyID=block.DialogPrm(1).Data;
decoyName=sprintf('%s%d','JetFlighterWithDecoy/Decoys/Decoy',decoyID);

% 脉冲信号上升沿触发,设置模型参数
if(block.InputPort(4).Data==1 && block.Dwork(1).Data==0)
fligherSpeed=block.InputPort(2).Data;
decoySpeed=[fligherSpeed(1) fligherSpeed(2) fligherSpeed(3)-30];
dcm=block.InputPort(3).Data;
docoySpeedInFlatEarth=inv(dcm)*decoySpeed';
v0=join(['[' string(docoySpeedInFlatEarth') ']']);
pos0=join(['[' string(block.InputPort(1).Data') ']']);
set_param(decoyName,'ParameterArgumentValues',struct('decoySpeed',char(v0),'decoyPos',char(pos0)));
block.Dwork(1).Data = 1;%使能信号
end

参考链接

  1. Simulink模块参数在线修改方法的研究,by 郑志波.
  2. Why do I get an error when specifying a Simscape component parameter with same name as built-in Simulink parameter?,by mathworks.
  3. Parameterize Instances of a Reusable Referenced Model,by mathworks.
  4. find_system,by mathworks.

数据可视化之二维图形

发表于 2020-07-31

“有图有真相”、“一图抵千言”,这些俗语充分体现了大数据时代图的重要性。与枯燥的数据相比,丰富多样的图形更能揭示数据背后的规律,更受普罗大众的欢迎。因此有必要了解和熟悉一些常用的图,以便根据数据选择合适的图形表示。

弦图 (Chord Diagram)

描述

弦图 (Chord Diagram) 可以显示不同实体之间的相互关系和彼此共享的一些共通之处,因此这种图表非常适合用来比较数据集或不同数据组之间的相似性。

节点围绕着圆周分布,点与点之间以弧线或贝塞尔曲线彼此连接以显示当中关系,然后再给每个连接分配数值(通过每个圆弧的大小比例表示)。此外,也可以用颜色将数据分成不同类别,有助于进行比较和区分。

弦图的缺点是过于混乱,尤其是当要显示太多连接的时候。

功能

  • 比较
  • 关系

旭日图

描述

也称为「多层饼形图」或「径向树图」。

这种图表通过一系列的圆环显示层次结构,再按不同类别节点进行切割。每个圆环代表层次结构中的一个级别,中心圆表示根节点,层次结构从这点往外推移。

之后圆环会按照其与原属切片的层次关系再被分割,分割角度可以是均等平分,或者与某个数值成比例。

我们也可以用不同颜色突出显示层次分组或特定类别。

功能

  • 层次结构
  • 部分对整体

参考链接

1.数据可视化工具目录,by datavizcatalogue.

D3入门教程

发表于 2020-07-03 | 更新于 2020-07-12

D3.js(D3或Data-Driven Documents)是一个使用动态图形进行数据可视化的JavaScript程序库。与W3C标准兼容,并且利用广泛实现的SVG、JavaScript和CSS标准,改良自早期的Protovis程序库。与其他的程序库相比,D3对视图结果有很大的可控性。D3是2011年面世的,同年的8月发布了2.0.0版。到2018年4月,D3已被更新到了5.5.0版。

D3.js已被数十万个网站使用,最常被运用在在线新闻网站呈现交互式图形、呈现数据数据的图表和呈现含有地理信息的数据。另外SVG的输出功能也使得D3.js能用于印刷出版物的绘制上。

技术原理

D3.js透过预先创建好迁入于网页中的JavaScript函数来选择网页元素、创建SVG元素、调整CSS来呈现数据,并且也可以设置动画、动态改变对象状态或加入工具提示来完成用户交互功能。使用简单的D3.js函数就能够将大型的数据数据结构与SVG对象进行绑定,并且能生成格式化文本和各种图表。其数据数据结构的格式可以是JSON、CSV(以逗号分隔的数据)或GeoJSON,也可以透过自己写JavaScript函数来读取其他或自定义格式的数据,例如Shapefile。

开发工具

  • rimraf

Node下的Unix命令 rm -rf。

  • json2module

将一个JSON对象转换成ES6模块。

  • Rollup

Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。ES6 模块最终还是要由浏览器原生实现,但当前 Rollup 可以使你提前体验。

  • tape

用于nodejs和浏览器的测试工具。

工程模板

请参考d3-project-template。

典型代码

当有数据而没有足够图形元素的时候,使用此方法可以添加足够的元素。

1
2
3
4
svg.selectAll("rect")   //选择svg内所有的矩形
.data(dataset) //绑定数组
.enter() //指定选择集的enter部分
.append("rect") //添加足够数量的矩形元素

当数组的长度与元素数量不一致(数组长度 > 元素数量 or 数组长度 < 元素数量)时呢?这时候就需要理解 Update、Enter、Exit 的概念。

如果数组为 [3, 6, 9, 12, 15],将此数组绑定到三个 p 元素的选择集上。可以想象,会有两个数据没有元素与之对应,这时候 D3 会建立两个空的元素与数据对应,这一部分就称为 Enter。而有元素与数据对应的部分称为 Update。如果数组为 [3],则会有两个元素没有数据绑定,那么没有数据绑定的部分被称为 Exit。

绘图流程

D3绘图流程

图1 D3绘图流程

参考链接

  1. Data-Driven Documents,by d3js.
  2. D3.js,by wikipedia.
  3. rimraf,by isaacs.
  4. json2module,by mbostock.
  5. Rollup,by rollup.
  6. tape,by substack.
  7. npm scripts 使用指南,by ruanyifeng.
  8. Webpack vs Rollup,by 余伯贤.
  9. npm运行项目报错—-Cannot find module ‘@babel/compat-data/corejs3-shipped-proposals’,by 吴小明.
  10. npm install 命令参数的一些简写方式,by 刘予川.
  11. Object.assign(),by mozilla.
  12. 第十章 理解 Update、Enter、Exit,by 馒头华华.
  13. SVG 图像入门教程,by ruanyifeng.
  14. JavaScript视口宽高、元素位置、滚动高度、尺寸属性,by 侠客有情剑无情QAQ.
  15. 【d3.js-03】shape-饼图,by PolarD.
  16. 二叉树遍历(前序、中序、后序、层次遍历、深度优先、广度优先),by zydoer.
  17. D3中常用的比例尺,by 江南陈酒.
  18. Flex 布局教程:语法篇,by ruanyifeng.
  19. 浅谈JavaScript获取元素的大小(高度和宽度)的方法,by html.
  20. mouseout、mouseover和mouseleave、mouseenter区别,by 海角在眼前.
  21. Building tooltips with d3.js,by d3-graph.
  22. 区分event对象中的[clientX,offsetX,screenX,pageX],by Rin阳.
  23. position:absolute相对哪个元素定位,by weiqing687.

如何处理前端异常

发表于 2020-07-02

参考链接

  1. 如何优雅处理前端异常?,by Jartto.

如何计算迎角的导数

发表于 2020-06-29 | 更新于 2020-06-30

在Matlab Simulink中使用Digital DATCOM Forces and Moments组件时,需要输入迎角的导数$d\alpha/dt$,可参考What is the time derivative of the angle of attack?。

迎角定义

在机体坐标系下,迎角和侧滑角如图1所示。

迎角和侧滑角

图1 迎角和侧滑角

于是,迎角定义为:

$$\alpha = \arctan \left(\frac{w}{u}\right)$$

其中速度分量$u$和$w$是随时间变化的函数。于是迎角的导数为:

$$\frac{d\alpha}{dt} = \frac{1}{1+\frac{w^2}{u^2}} \left(\frac{w}{u}\right)’= \frac{w’u - wu’}{u^2+w^2}$$

参考链接

  1. What is the time derivative of the angle of attack?,by aviation.

分布式哈希表DHT和P2P技术

发表于 2020-06-24

一篇介绍DHT和P2P技术的文章,浅显易懂,值得收藏。

分布式哈希表 (DHT) 和 P2P 技术

参考链接

  1. 分布式哈希表 (DHT) 和 P2P 技术,by Luyu Huang.

如何培养领导力

发表于 2020-06-19 | 更新于 2023-12-24

俗话说,一个人走得快,一群人走得远。作为一个团队的领导,拥有高超的领导力,是团队走向成功的关键。那么如何培养提高自己的领导力呢?美国一个创业者给出了一个方法。按照下面的四个阶段,就能让自己成为一个优秀的领导者。

第一阶段:熟悉自己的业务,知道问题在哪里,怎样可以解决。

领导者是给大家指方向的,你必须先知道要走哪个方向,才能带领别人,这是领导力的基础。

第二阶段:培养说服能力,能说服他人,问题可以按照你说的方式解决。

领导力的表现是,他人愿意服从你。这不能都靠制度压服,而要让他人真心觉得你是对的。如果你可以让他人相信你,你就可以领导。

第三阶段:激发他人的热情,让他们产生解决问题的热情。

说服他人的更高境界,是让他们真正投身进来,自觉发挥自己的潜力,全力以赴解决需要解决的问题。好的领导和差的领导,区别就在于能否激励下级,让每个人都知道自己的职责,努力工作。

第四阶段:你培养其他人的领导能力。

如果你离开,团队也能正常运作下去,说明一切已经制度化了,你的领导已经成功了。这时,你可以让其他人接管团队,自己去实现下一个目标。

参考链接

  1. The Culture of Leadership,by Ben Mappen.
  2. 科技爱好者周刊(第 112 期):如何培养领导力,by ruanyifeng.

CSS技巧记录总结

发表于 2020-06-08 | 更新于 2023-07-28

层叠样式表 (Cascading Style Sheets,缩写为 CSS),是一种 样式表 语言,用来描述 HTML 或 XML(包括如 SVG、MathML、XHTML 之类的 XML 分支语言)文档的呈现。CSS 描述了在屏幕、纸质、音频等其它媒体上的元素应该如何被渲染的问题。下面记录一下CSS的“奇技淫巧”。

使用伪元素创建向右箭头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.targetDiv::after{
content: " ";
display: inline-block;
height: 8px;
width: 8px;
border-width: 2px 2px 0 0;
border-color: #b2b2b2;
border-style: solid;
transform: matrix(.71,.71,-.71,.71,0,0);
position: relative;
top: -2px;
position: absolute;
top: 50%;
margin-top: -5px;
left:90%;
right: 0;
}

CSS3 框大小

CSS3 box-sizing 属性可以设置 width 和 height 属性中包含了 padding(内边距) 和 border(边框)。

默认情况下,元素的宽度与高度计算方式如下:

width(宽) + padding(内边距) + border(边框) = 元素实际宽度

height(高) + padding(内边距) + border(边框) = 元素实际高度

但是,如果在元素上设置了CSS3 box-sizing: border-box; 则 padding(内边距) 和 border(边框) 也将包含在 width 和 height 中。

CSS writing-mode 文字竖排

writing-mode 属性定义了文本在水平或垂直方向上如何排布。

语法格式如下:

1
writing-mode: horizontal-tb | vertical-rl | vertical-lr | sideways-rl | sideways-lr
  • horizontal-tb:水平方向自上而下的书写方式。即 left-right-top-bottom
  • vertical-rl:垂直方向自右而左的书写方式。即 top-bottom-right-left
  • vertical-lr:垂直方向内内容从上到下,水平方向从左到右
  • sideways-rl:内容垂直方向从上到下排列
  • sideways-lr:内容垂直方向从下到上排列

CSS 箭头和三角形

CSS画箭头和三角形都是利用div标签的边框属性,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 三角形
<div class="box"></div>
// css代码
.box {
width: 0;
height: 0;
border: 100px solid red;
border-color: red transparent transparent transparent;
}

// 箭头
<div class="box"></div>
// css代码
.box {
margin-top: 50px;
width: 100px;
height: 100px;
border-top: 10px solid red;
border-right: 10px solid red;
transform: rotate(45deg);
}

height:100%不生效问题

浏览器按照从上到下,从外到内的顺序渲染DOM内容。因此当父元素没有设置高度值或者设为绝对定位,则子元素的height:100%不会不生效。

div的高度是由什么决定?是由它文档流中元素的高度的总和。

什么是文档流(Normal Flow):指的是元素排版布局过程中,内联元素会默认自动从左往右,块级元素从上往下的流式排列方式。并最终窗体自上而下分成一行行,并在每行中从左至右的顺序排放元素。

脱离文档流(常见):

  • float:left;
  • position: absolute;
  • position:fixed;

单行缩略..以及多行缩略

html单行缩略方法:

1
2
3
4
5
.oneline {
white-space: nowrap; //强制文本在一行内输出
overflow: hidden; //隐藏溢出部分
text-overflow: ellipsis; //对溢出部分加上...
}

CSS尺寸单位 % px em rem

在CSS中,尺寸单位分为两类:相对长度单位和绝对长度单位。相对长度单位按照不同的参考元素,又可以分为字体相对单位和视窗相对单位。字体相对单位有:em、ex、ch、rem;视窗相对单位有:vw、vh、vmin、vmax几种。绝对长度单位则是固定尺寸,它们采用的是物理度量单位:cm、mm、in、px、pt以及pc。但在实际应用中,我们使用最广泛的则是em、rem、px以及百分比(%)来度量页面元素的尺寸。

  • px:为像素单位。它是显示屏上显示的每一个小点,为显示的最小单位。它是一个绝对尺寸单位,是不能变动的;
  • em:它是描述相对于应用在当前元素的字体尺寸,所以它也是相对长度单位,可以变动。一般浏览器字体大小默认为16px,则2em == 32px;
  • rem:它是描述相对于当前根元素字体尺寸,除了描述对象与em不同其余都和em一样。
  • %: 百分比,它是一个更纯粹的相对长度单位,可以变动。它描述的是相对于父元素的百分比值。如50%,则为父元素的一半。

CSS使网站黑白灰效果的代码

使用如下CSS即可:

1
2
3
4
5
6
7
8
html {
filter: grayscale(100%);
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
-webkit-filter: grayscale(1);
}

代码释义:filter 是滤镜的意思,filter:gray 的意思就是说给页面加上一个灰度的滤镜,所以 html 里面的所有内容都会变成黑白的了。不过这个滤镜对于 Chrome 和 Safari 浏览器是无效的,所以下面会有一行 -webkit-filter: grayscale(100%); 这个样式是专属于使用 webkit 内核的浏览器的,意思和 filter: gray; 差不多,只是写法不同罢了。

CSS打印时隐藏输入框占位符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@media print {
::-webkit-input-placeholder { /* WebKit browsers */
color: transparent;
}
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: transparent;
}
::-moz-placeholder { /* Mozilla Firefox 19+ */
color: transparent;
}
:-ms-input-placeholder { /* Internet Explorer 10+ */
color: transparent;
}
}

CSS float属性

CSS 的 Float(浮动)使元素脱离文档流,按照指定的方向(左或右发生移动),直到它的外边缘碰到包含框或另一个浮动框的边框为止。

文档流是是文档中可显示对象在排列时所占用的位置/空间,而脱离文档流就是在页面中不占位置了。

当元素设置float浮动后,该元素就会脱离文档流并向左/向右浮动,直到碰到父元素或者另一个浮动元素,浮动元素会造成父元素高度塌陷。

清除浮动的影响的方法有:

  • 设置父布局的高度

设置父标签合适的高度,前提必须确定子布局的高度,来计算父布局的合适高度,包裹住子布局。

  • 受影响的元素加clear属性

给受影响的div加clear,清除浮动的影响

  • overflow清除浮动

父级标签的样式里面加: overflow:hidden;

  • 空div法

在最后一个浮动的盒子的后面,新添加一个标签。然后设置clear清除浮动。

  • 伪对象法

为父标签添加伪类After,设置空的内容,并且使用clear:both;

CSS width属性

css的三大特性分别是 继承性,层叠性,和优先级。

css的继承性指的被包在内部的标签拥有外部标签的样式性,子元素可以继承父元素的属性。但也不是所有的css属性都有继承性的。

  • 只有块元素才可以默认“继承”其父元素的width.
  • 浮动元素和定位元素也是不默认(不自动)“继承”其父元素宽度的。

参考链接

  1. CSS(层叠样式表),by mozilla.
  2. CSS3 框大小,by runoob.com.
  3. 不让padding影响元素的宽度,by DecemberCafe.
  4. 改变CSS世界纵横规则的writing-mode属性,by 张鑫旭.
  5. 重新认识Pixel、DPI / PPI 以及像素密度,by Leon.
  6. CSS画三角形,箭头,by 麦西的西.
  7. 如何用 CSS 画三角形和箭头,by 前端技术.
  8. 深入理解CSS系列(二):为什么height:100%不生效?,by ChessZhang.
  9. height:100%失效解决办法,by 当然我没扯淡.
  10. css之单行缩略..以及多行缩略,by 秋天的故事.
  11. CSS尺寸单位 % px em rem 详解,by HDWK.
  12. 如何修改placeholder样式,by 风火星辰.
  13. 一行 CSS 代码实现整个网站网页变黑白灰的效果,by 老唐.
  14. CSS hide placeholder on print [duplicate],by stackoverflow.
  15. 深入理解float浮动属性,by 知乎用户1sIGTn.
  16. css的继承之width属性(容易忽略),by 秋天的鱼.

关于疾病的思考

发表于 2020-06-05

世界上绝大多数人不会因努力工作而致富,实现个人财务自由,但是却会因一场大病而使整个家庭陷入贫困。因此,保持健康的身体,远离疾病也是一种投资,虽不会因此致富,但却能提高我们的生活质量,减少看病支出,间接实现财富的增值。那么如何保持身体健康,远离疾病呢?

人会生病,主要受到三个因素的影响:

  • 先天性因素,即从娘胎里带出来的疾病。
  • 接触性因素,分为环境因素和饮食因素。环境因素即人处在糟糕的环境中导致疾病。饮食因素即人摄入不健康的食物导致疾病。
  • 生活性因素。人的身体像机器一样,需要爱护和保养,不正常的生活作息规律将导致疾病。

先天性因素导致的疾病是无法避免的,接触性因素中的环境因素可以很好的避免,大不了换个环境,但接触性因素中的饮食因素和生活性因素就需要人的毅力去克服。保持良好的生活作息习惯和遵循健康的饮食习惯将是我们对抗疾病的主战场。

参考链接

  1. 如何致富不靠运气,by jackhuang.
上一页1…272829…53下一页

Jack Huang

528 日志
68 标签
© 2025 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse