JS使用前询问,依据类库开采及框架介绍
分类:前端技术

D3 力导向图和 WebGL 的咬合利用

2017/07/14 · JavaScript · D3js, WebGL

原稿出处: geekplux   

D3 是眼下最风靡的数码可视化库,WebGL 是当前 Web 端最快的绘图本领。由于质量难题的局限,将二者结合的品味更多(如),本文将尝试用 D3 的力导向图 和 Three.js 和 PixiJS 结合。全文阅读完大约 5 分钟,因为你根本应该看代码。

做多少可视化时,必然会思量性能的难题。以前数量可视化都是用 Qt 等 GUI,后来慢慢迁移到了迅猛发展的浏览器上海展览中心示,Web 的特性难点成了绝大相当多可视化的受制,特别是在三维可视化,或数据量特别大的时候。未来主流的 Web 可视化手艺为二种:SVG、Canvas 和 WebGL,难易程度和性情如下图:

图片 1Web visualization tech

SVG 的亮点超级多,编辑简单,交互作用便捷,灵活性超级高,行业内部成熟的可视化学工业具(如 d3)都是用的 SVG。然而种种 SVG 都以三个 DOM 成分,随着它的数码上来之后,人机联作开头慢的难以忍受。那是因为每当改善三个DOM 对象,只要这么些指标在文书档案里,接着在浏览器里就能够发生两个动作,一个叫 Reflow(重排,正是重新制版),另多少个叫 Repaint(重绘,正是重新渲染页面)。那七个动作不必然都会发出,但尽管被改换的 DOM 当前可以看见的话,那么就能够先重排,后重绘。绘制品质上 canvas 和 SVG(DOM 成分)应该大致,但后边五个能够节约重排进程,因而质量更加高。但是,WebGL 的本性更胜一筹,因为 WebGL 使用 GPU 加快渲染,GPU 在分布总结方面有相对优势(图像管理、深度学习都在用,显卡已经卖疯了)。例子:用 WebGL 绘制 二〇〇一00 个点的动漫()

WebGL 固然威力无穷,可是写起来比较难受,画个三角形差不离要 100 行代码。所以重重人对 WebGL 举行了打包。上面图中提到的多个 Three.js 和 PixiJS 是当前最盛行的三款 WebGL 库,当然还可能有新兴的 regl 在二〇一两年的 OpenVis 上海高校放异彩。本文尝试用前两个和 d3-force 结合(项目代码在这里),前面借使一时光来讲,笔者会把施用 regl 和原生 WebGL 的例证也添补进去(作者精晓那是个 flag)。

Three.js是贰个了不起的开源WebGL库,WebGL允许JavaScript操作GPU,在浏览器端达成真正含义的3D。可是当前那项技艺还处在进化期,资料极为恐慌,爱好者学习为首要经过德姆o源码和Three.js本身的源码来上学。

点评:前边大家看到了选取原生的WebGL API开拓是多么的累,只因如此大方的WebGL框架被开采出来,那么些框架区别档期的顺序的卷入了成立3D场景的各个因素你能够火速创制供给的3D场景,感兴趣的对象能够驾驭下,大概本文对你有着支持

正文

率先大家要领悟什么样是力导向图和什么运用 d3-force。d3 4.0 之后,我将其模块化,force 这几个模块是遵照 velocity Verlet 落成了物理粒子之间的效率力的仿真,常用来互联网或提到结构数据。即你把互联网中的节点想象成二个个粒子,它们中间相互有功用力,所以不停的拉扯,直到趋于一个安静意况,具体能够看本人 demo 中可视化出来的指南。

图片 2Demo 效果图

仔细看 demo 中的源码能够开采,用 three.js 和用 pixi.js 完成起来卓殊相通,个中有关力导向图的第一代码是下面几句:

JavaScript

const simulation = d3.forceSimulation(卡塔尔(قطر‎ // 创造叁个功用力的仿真,但当时还未有运行 .force('link', d3.forceLink(卡塔尔国.id((d卡塔尔 => d.id卡塔尔(英语:State of Qatar)卡塔尔 // 为边之间增添 Link 型效用力 .force('charge', d3.forceManyBody(卡塔尔(英语:State of Qatar)卡塔尔国 // 钦命节点间的成据守类型为 Many-Body 型 .force('center', d3.forceCenter(width / 2, height / 2卡塔尔国卡塔尔 // Centering 作用力钦定布局围绕的着力

1
2
3
4
const simulation = d3.forceSimulation() // 创建一个作用力的仿真,但此时还没启动
  .force('link', d3.forceLink().id((d) => d.id)) // 为边之间添加 Link 型作用力
  .force('charge', d3.forceManyBody()) // 指定节点间的作用力类型为 Many-Body 型
  .force('center', d3.forceCenter(width / 2, height / 2)) // Centering 作用力指定布局围绕的中心

d3-force 提供了四种成效力,分别是 Centering、Collision、Links、Many-Body、Positioning。当时大家早就创办好带有各类力的仿真器了,接下去供给运维它:

JavaScript

simulation .nodes(data.nodes卡塔尔(قطر‎ // 依照 data.nodes 数组来总括点之间的效率力,约等于不停计算节点的 xy 坐标 .on('tick', ticked卡塔尔(قطر‎ // 每一遍 tick 调用 ticked simulation.force('link').links(data.links卡塔尔国 // 依照 data.links 数据总括边之间的效率力

1
2
3
4
5
simulation
  .nodes(data.nodes) // 根据 data.nodes 数组来计算点之间的作用力,相当于不停计算节点的 xy 坐标
  .on('tick', ticked) // 每次 tick 调用 ticked
simulation.force('link')
  .links(data.links) // 根据 data.links 数据计算边之间的作用力

至今停止一个力导向图的虚假就伊始了,那么怎么把这么些节点和边显示出来吧?让我们继承看源码,以 three.js 为例:

JavaScript

const scene = new THREE.Scene() const camera = new THREE.OrthographicCamera(0, width, height, 0, 1, 1000) const renderer = new THREE.WebGLRenderer({alpha: true}) renderer.setSize(width, height) container.appendChild(renderer.domElement) // container 这里是 document.body

1
2
3
4
5
const scene = new THREE.Scene()
const camera = new THREE.OrthographicCamera(0, width, height, 0, 1, 1000)
const renderer = new THREE.WebGLRenderer({alpha: true})
renderer.setSize(width, height)
container.appendChild(renderer.domElement) // container 这里是 document.body

在 Three.js 中显示场景需求全体三要素:场景、照相机、渲染器。单反相机就也就是我们的肉眼,它对着渲染好的情景就一定于把场景成像到了相机中,这里的卡片机我们用的是平行投影相机,渲染器大家采取的是 WebGL 渲染器。设置好渲染器的分寸,把它增加到页面包车型客车成分上,相当于增加了二个 <canvas> 成分。接下来,大家转移每种节点和边的样子:

JavaScript

data.nodes.forEach((node) => { node.geometry = new THREE.CircleBufferGeometry(5, 32) node.material = new THREE.MeshBasicMaterial({ color: colour(node.id) }) node.circle = new THREE.Mesh(node.geometry, node.material) scene.add(node.circle) }) data.links.forEach((link) => { link.material = new THREE.LineBasicMaterial({ color: 0xAAAAAA }) link.geometry = new THREE.Geometry() link.line = new THREE.Line(link.geometry, link.material) scene.add(link.line) })

1
2
3
4
5
6
7
8
9
10
11
12
data.nodes.forEach((node) => {
  node.geometry = new THREE.CircleBufferGeometry(5, 32)
  node.material = new THREE.MeshBasicMaterial({ color: colour(node.id) })
  node.circle = new THREE.Mesh(node.geometry, node.material)
  scene.add(node.circle)
})
data.links.forEach((link) => {
  link.material = new THREE.LineBasicMaterial({ color: 0xAAAAAA })
  link.geometry = new THREE.Geometry()
  link.line = new THREE.Line(link.geometry, link.material)
  scene.add(link.line)
})

套路都平等,都以先建二个几何体,然后设置质地的体裁,增加参加景中就好了。接下来只要在刚刚提到的 ticked 这些回调函数中把节点和边的坐标更新一下就好了:

JavaScript

function ticked () { data.nodes.forEach((node) => { const { x, y, circle } = node circle.position.set(x, y, 0) }) data.links.forEach((link) => { const { source, target, line } = link line.geometry.verticesNeedUpdate = true line.geometry.vertices[0] = new THREE.Vector3(source.x, source.y, -1) line.geometry.vertices[1] = new THREE.Vector3(target.x, target.y, -1) }) render(scene, camera) }

1
2
3
4
5
6
7
8
9
10
11
12
13
function ticked () {
  data.nodes.forEach((node) => {
    const { x, y, circle } = node
    circle.position.set(x, y, 0)
  })
  data.links.forEach((link) => {
    const { source, target, line } = link
    line.geometry.verticesNeedUpdate = true
    line.geometry.vertices[0] = new THREE.Vector3(source.x, source.y, -1)
    line.geometry.vertices[1] = new THREE.Vector3(target.x, target.y, -1)
  })
  render(scene, camera)
}

是或不是比想象的简要多了?假如以上有怎么着地点看不懂,表明您或者对 Three.js 不是很明白,但是没什么,它的文书档案写的很好,入门异常快。希望这篇作品能给你带给一些声援,做了点一线的孝敬,很惭愧 :卡塔尔国

1 赞 1 收藏 评论

图片 3

国外网址 aerotwist.com 有六篇较为轻松的入门教程,作者尝试着将其翻译过来,与大家大饱眼福。
本身在部分尝试项目中动用了Three.js,小编发现它对急速上手浏览器3D编制程序确实很有赞助。通过Three.js,你不仅能够成立相机、物体、光线、质感等等,还足以选用着色器,能够垄断(monopoly卡塔尔(英语:State of Qatar)选拔何种工夫(WebGL、Canvas或SVG)在网页上渲染你的3D图形。Three.js是开源的,你以至能够参加到那个项目中来。但现行反革命,笔者将把重大放在幼功的介绍上,作者将向您来得如何使用这些引擎上。

前方大家看出了利用原生的WebGL API开荒是何其的累,正因为那样,大批量的WebGL框架被支付出来。使用那几个框架,你能够非常快创立供给的3D场景。这一个框架差异水平的包裹了成立3D场景的各类要素,举个例子场景,相机、模型、光照、材质等等;使用那几个包裹起来的对象,就足以很简短的开创供给的3D场景,那样您就只须要把越来越多精力放在逻辑方面就能够了。

纵然Three.js如此美妙,但有时候它也会令人抓狂。例如,你将花销大批量日子读书例程,做一些逆向工程(在本身的情景下)来规定某个函数的功力,有时还要去GitHub上发问。借令你需求咨询,Mr. doob和AlteredQualia是极好的选项。

当下并不曾哪三个兼有能赶上其余框架的优势,选用怎么样的框,依旧看个人向往吧,不过接受框架的时候,个人以为依然多看看框架最终的换代时间,接收稳固更新的框架能让您生机勃勃味能利用上风行的特色,令你的程序稳固性越来越好。

1.基础
自家只要你的三个维度图形学知识过关,并且也在一定水平上调整了JavaScript。假诺不是如此,这先去学一点吧,不然直接看那篇教程,恐怕会感觉思疑。

上面包车型大巴事例就接纳了Three.js框架实行付出。
Three.js是三个比较完备的开源框架,它优异的包装的3D场景的各类要素。你能够用它来相当轻便的去成立录像机,模型,光照,材料等等。你还足以选用分歧的渲染器,Three.js提供了各个渲染方式,你能够筛选接纳canvas来渲染,也能够使用WebGL恐怕SVG来进展渲染。

在大家的三个维度世界里,大家有以下这个东西。作者会带你一步一步创造它们。
1.场景
2.渲染器
3.相机
4.实体(带有材料的)
当然,你也得以成立些此外的什么样东西,小编也可望你那样做。
2.浏览器支持
轻易地看一下浏览器的支撑情况吧。Google家的Chrome浏览器扶持Three.js,在自个儿的尝试里,无论是对渲染器的支撑程度照旧JavaScript解释器的运行速度,Chrome都以做得最棒的:它援助Canvas、WebGL和SVG,何况运转得要命快。FireFox浏览器排在第四位,它的JavaScript引擎的速度比Chrome慢了半拍,可是对渲染器的支撑也很棒,并且FireFox的进程,随着版本更新也更加快。Opera浏览器正在稳步扩展对WebGL的扶植,Mac上的Safari浏览器有三个敞开WebGL的选项。总体上,那多少个浏览器仅仅协助Canvas渲染。微软家的IE9今后只扶植Canvas渲染,况且微软犹如并不乐意扶助WebGL那一个新特征,所以我们前些天自然不会用IE9来坚实验。
3.安装场景
假若你已经筛选了三个支撑全数渲染技巧的浏览器,何况你希图通过Canvas或WebGL来渲染场景(那是更标准的抉择)。Canvas比WebGL有着更广阔地帮衬,但是WebGL能够一贯在GPU上操作,那意味着你的CPU能够小心地管理非渲染类的办事,比如物理引擎或与客户交互作用等。

 别的,Three.js能够加载非常多格式的3D文件,你的模子文件能够来自Blender,Maya,Chinema4D,3DMax等等。何况内置了相比底子的东西:(球体卡塔尔国Spheres, (飞机卡塔尔(英语:State of Qatar)Planes, (立方体卡塔尔(英语:State of Qatar) Cubes, (圆柱体卡塔尔Cylinders。Three.js创设那一个物心得极度的轻便。

甭管你筛选何种渲染器,你都必得深深记住在心的是:JavaScript代码需求优化。三个维度展现对浏览器来讲不是风流浪漫项轻易的专门的学问(现在亦可这么做就很宏大了),所以意气风发旦你的渲染太慢了,你必要知道您代码的瓶颈在哪儿,假使或然,改过它。

好了,不赘述了,直接看代码:

说了那样多,作者想你曾经下载好Three.js源代码,况且将它引入了你的html文书档案了。那么什么样开头创立贰个风貌呢?就如那样:

代码如下:

复制代码 代码如下:

<!DOCTYPE html>
<html>
<head>
<title>threeJSDemo </title>
<meta charset="utf-8">
<style>
body
{
margin:0px;
background-color:#B0B0B0;
overload:hidden;
}
</style>
</head>
<body>
<script src="Three.js"></script>
<script>
var camera,scene,renderer;
var mesh;
init();
animate();

// 设置场景大小
var WIDTH = 400,
HEIGHT = 300;
// 设置有个别相机参数
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;
// 获取DOM布局中的成分
// - 借使大家使用了JQuery
var $container = $('#container');
// 创设渲染器、相机和现象
var renderer = new THREE.WebGLRenderer();
var camera =
new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR);
var scene = new THREE.Scene();
// 将相机出席场景
scene.add(camera);
// 相机的发端地点为原点
// 将相机拉回来一些(译者注:那样本领看出原点)
camera.position.z = 300;
// 运维渲染器
renderer.setSize(WIDTH, HEIGHT);
// 将渲染器加到DOM结构中
$container.append(renderer.domElement);

function init(){
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(70,window.innerWidth / window.innerHeight,1,1000);
camera.position.z = 400;
scene.add(camera);
geometry = new THREE.CubeGeometry(200,200,200);
material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x = 0.05;
mesh.rotation.y = 0.05;
renderer.render( scene, camera );
}
</script>
</body>
</html>

你看,简单吧!
4.创设网格表面
今昔我们有了二个景观,二个单反相机和三个渲染器(在本人的例子里,当然是二个WebGL渲染器),但大家其实什么还没画呢。事实上,Three.js提供了载入某三种标准格式3D文件的帮衬,若是你在Blender,Maya,Cinema4D或是什么别的工具中国建工业总会公司模,那差不离太棒了。为了轻巧(毕竟那才刚带头吧!)大家先来虚构基元。基元便是大旨的几何表面,譬喻最中央的圆球、平面、立方体、圆柱体。利用Three.js能够很实惠地创制那么些基元:

以此是整个的代码,相对于前方使用WebGL的API的代码,那么些差超少就是太轻松了。
代码很直观,就那么几步:

复制代码 代码如下:

  1. 创造场景scene。
  2. 创办录像机camera。
  3. 创制/加载模型geometry。
  4. 加载材质material。
  5. 渲染模型对象mesh(是由geometry和material组成卡塔尔(英语:State of Qatar)。
  6. 启用动漫。

// 设置球体参数(译者注:球体被分割为16×16的网格,假设后四个参数取4、2,则生成一个八面体,请想象)
var radius = 50,
segments = 16,
rings = 16;
// material覆盖在geometry上,生成mesh
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(
radius,
segments,
rings),
sphereMaterial);
// 将mesh插手参与景中
scene.add(sphere);

这是各种框架都提供的效果,使用分裂的框架除了函数的称呼可能不一致以外,这个手续基本都以均等的。上面包车型地铁参阅中列出了过多的框架学习文书档案,大家可以选三种学习一下。

好了,可是球体上的材质呢?在代码中大家应用了二个sphereMaterial变量,我们还未有概念它吧。那大家就先来拜会怎么开创质感吧。
5.材质
必然,那是Three.js最得力的有些了。那某些提供了几个要命易用的通用材料模型:
1.Basic质地:表示大器晚成种不思虑光照的材料,未来只可以这么说了。
2.兰伯特材料:(译者注:Lambert面,各向同种性别反射)。
3.Phong材料:(译者注:冯氏面,有光线的外界,介于镜面反射和兰伯特反射之间的反光,描述真实世界的反射)。

针对模型数据,作者还想说一点,因为JSON短小精悍,所以相比切合网络传输。将来它大概变为最切合WebGL的模子数据格式,所以广大的框架都起来帮助JSON格式的模子数据。

除此之外,还应该有部分别样门类材料,轻易起见,就留下您自身探究。事实上,在运用WebGL类型的渲染器时,质地实在太好用了。为何呢?因为在原生WebGL种你必得亲自为各样渲染编写着色器,而着色器自身正是个庞大的工程:轻易地说着色器是采取GLSL语言(OpenGL的着色器语言)写的,用来操作GPU的次序,那代表你要在数学上效仿光照,反射等等,那飞跃就成为生机勃勃项极为复杂的办事。多亏有了Three.js你才得以不用去团结编写着色器,当然,假诺您想亲身编写的话,你能够使用MeshShaderMaterial,可以预知那是很灵巧的设定。

实用参考:
支付中央:

现行反革命,让大家用兰伯特面材质覆盖球体:

精品在线开垦工具:
各样框架根基教程:
WebGL粤语教程:
Oak3D粤语教程:
CubicVR3D官网:
Three.js图形库:
各样框架的征集贴:

复制代码 代码如下:

// 成立球体表面包车型的士材料
var sphereMaterial =
new THREE.MeshLambertMaterial(
{
color: 0xCC0000
});

值得提议的是,创设材料的时候,除了颜色还恐怕有好多别样参数能够钦赐,举例发光度和条件贴图。你能够须要寻觅这一个Wiki页面来承认哪些是何等属性能够设置在材质上,或Three.js引擎提供的别的对象上。
6.光
设若你今后就想渲染场景,你会见到二个青黛色的圆。即使大家在球体上覆盖了Lambert面材料,但气象里不曾光。所以遵照暗中同意设定,Three.js会苏醒到满情状光,物体的看起来的颜料正是实体表面包车型客车颜色。让大家抬高三个简约的点光源:

复制代码 代码如下:

// 成立三个点光源
var pointLight =
new THREE.PointLight(0xFFFFFF);
// 设置点光源的岗位
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
// 将点光源参预场景
scene.add(pointLight);

7.渲染循环
大名鼎鼎,关于渲染器的整整都设置好了。防微杜渐,大家今后只供给:

复制代码 代码如下:

// 画!
renderer.render(scene, camera);

您很恐怕像频仍渲染,而不是只渲染壹次,所以风流浪漫旦你要去做一个巡回,你应有选择requestAnimationFrame。那是现阶段最佳的,在浏览器中管理动漫的方法,固然还未有曾拿走最完备的辅助,但小编生硬提出你去看意气风发看PaulIrish的博客。
8.通用的指标属性
生龙活虎经您花点时间去浏览三回Three.js的源代码,你会意识众多指标都一而再自Object3D。那么些基类包罗了广大平价的天性,比如地点、旋转和缩放的音信。非常的,大家的球体是一个Mesh对象,而Mesh对象世袭自Object3D对象,可是又追加了些自个儿的习性:geometry和material。为何要说那几个?因为您分明不会只知足于荧屏中三个怎么样都不做的圆球,而这几个(译者注:基类中的)属性允许你操作Mesh对象更底层的内部情状和有滋有味的材料。

复制代码 代码如下:

// sphere是一个mesh对象
sphere.geometry
// sphere蕴含了后生可畏都部队分点和面包车型客车新闻
sphere.geometry.vertices // 二个数组
sphere.geometry.faces // 另贰个数组
// mesh对象世襲自object3d对象
sphere.position // 包含x,y,z
sphere.rotation // 同上
sphere.scale // ... 同上

9.讨厌的神秘
本人梦想那样说你能非常的慢弄通晓:便是只要您改改了,比方说,一个mesh对象的极点属性vertices,你会发今后渲染循环中,什么都没变。为何?因为Three.js将mesh对象的音讯缓存为某种优化构造了。你实在要做的是给Three.js壹个标记,告诉它生龙活虎旦什么东西改换了,须要再度计算缓存中的构造:

复制代码 代码如下:

// 设置geometry为动态的,那样才同意改换当中的终点
sphere.geometry.dynamic = true;
// 告诉Three.js,须求重新计算极点
sphere.geometry.__dirtyVertices = true;
// 告诉Three.js,要求重新总结极点
sphere.geometry.__dirtyNormals = true;

还会有更加多的标记,但本人意识那八个是最可行的。你应该仅仅标记那个的确须要实时总计的品质来幸免无谓的运算花销。
10.小结
自家盼望那篇轻便的牵线对你具有助于。没什么能赶得上卷起袖子亲手施行了,我刚强建议你这么做。在浏览器里面运维3D程序很风趣,何况动用像Three.js那样三个引擎免去了累累劳神,让你意气风发开端就能够只顾于那个的确cool的作业。

自己将那篇教程的源码打包了,你能够下载下来充任生龙活虎份参照他事他说加以考查。

...

本文由pc28.am发布于前端技术,转载请注明出处:JS使用前询问,依据类库开采及框架介绍

上一篇:JS入门教程,js职业原理 下一篇:没有了
猜你喜欢
热门排行
精彩图文
  • 运动端适配方案,多终端的适配实施方案
    运动端适配方案,多终端的适配实施方案
    移动端适配方案(下) 2017/01/25 · CSS ·移动端 本文作者: 伯乐在线 -risker。未经作者许可,禁止转载! 欢迎加入伯乐在线 专栏作者。 上一篇介绍了像素和视
  • 内部存储器分析工具简要介绍,内部存款和储蓄
    内部存储器分析工具简要介绍,内部存款和储蓄
    4类 JavaScript 内存泄漏及如何避免 2016/05/26 · JavaScript· 1 评论 ·内存泄漏 本文由 伯乐在线 -涂鸦码龙翻译。未经许可,禁止转载! 英文出处:SebastiánPeyro
  • HTML也可以静态编译,损害了复用性
    HTML也可以静态编译,损害了复用性
    React.Component 损害了复用性? 2016/09/07 · 底蕴技能 ·binding.scala,data-binding,React,scala.js 本文笔者: 伯乐在线 -ThoughtWorks。未经笔者许可,防止转发! 接待插足
  • 品质的法门
    品质的法门
    9 种改革 AngularJS 品质的艺术 2017/07/20 · JavaScript· AngularJS 初藳出处: JustinSpencer   译文出处:oschina    AngularJS 是当下利用非常遍布的 web app应用框架,随
  • 高质量滚动,实例解析防抖动和节流阀
    高质量滚动,实例解析防抖动和节流阀
    实例解析防抖动和节流阀 2016/04/26 · JavaScript· DOM 本文由 伯乐在线 -涂鸦码龙翻译。未经许可,幸免转发! 立陶宛共和国(Republic of Lithuania卡塔尔语出处: