suchen
HeimWeb-FrontendH5-Tutorial3D-Netzwerktopologiediagramm von HTML5 WebG

In diesem Artikel wird hauptsächlich das 3D-Netzwerktopologiestrukturdiagramm von HTML5 WebG vorgestellt. Wir werden die 3D-Netzwerktopologiestruktur im Detail mit Bildern und Texten vorstellen und hoffen, allen zu helfen.

3D-Modelle werden heutzutage in den unterschiedlichsten Bereichen eingesetzt. Sie werden in der Medizinindustrie zur Herstellung präziser Organmodelle verwendet; in der Filmindustrie werden sie in Zeichentrickfiguren, Objekten und realistischen Filmen verwendet; Sie werden als genaue Modelle chemischer Verbindungen verwendet. Die Architekturindustrie verwendet sie, um geplante Gebäude oder Landschaftsausdrücke zu demonstrieren In diesem Bereich wird mit der Konstruktion dreidimensionaler geologischer Modelle begonnen. 3D-Modelle werden häufig animiert, beispielsweise in Spielfilmen sowie Computer- und Videospielen. Sie können innerhalb eines 3D-Modellierungstools oder einzeln verwendet werden. Um Animationen einfacher erstellen zu können, werden dem Modell in der Regel einige zusätzliche Daten hinzugefügt. Beispielsweise verfügen einige 3D-Modelle von Menschen oder Tieren über ein vollständiges Skelettsystem, sodass die Bewegung realistischer aussieht und die Bewegung über Gelenke gesteuert werden kann und Knochen.

All dies gibt uns Front-End-Entwicklern das Gefühl, dass es großartig wäre, wenn wir 3D-Effekte erzielen könnten, ohne Unity3d oder andere Spieleentwicklungstools zu lernen, und Bewegungen oder Richtungen mit Code genau steuern könnten. . . Deshalb habe ich die 3D-Komponente in HT For Web verwendet, um ein kleines Beispiel zu implementieren und dabei die meisten Funktionen der 3D-Komponente in HT zu verwenden. Der Zweck dieses Beispiels besteht darin, ein gutes Verständnis der 3D-Komponente zu erlangen und zu versuchen, sie in sie umzusetzen ein Beispiel, damit andere es bei Bedarf nachschlagen können.

Werfen wir zunächst einen Blick auf die Renderings der Gesamtimplementierung:

3D-Netzwerktopologiediagramm von HTML5 WebG

Verwenden Sie HT for Web, um drei Ebenen aus dem zu erstellen Vorhandene 3D-Vorlage Die Bodenplatte ist nicht das Problem. Das Problem ist, wie man die „Computer“- und „Schrankkomponenten“ auf der ersten Ebene im Bild platziert. Ich habe die obj-Formatdatei aus dem Internet heruntergeladen und dann die Funktion ht.Default.loadObj(objUrl, mtlUrl, params) in HT verwendet, um das Modell hineinzuladen. Den Parameterteil finden Sie unter http://www .hightopo.com/guide..., der Code lautet wie folgt:

ht.Default.loadObj('obj/机柜组件1.obj', 'obj/机柜组件1.mtl', {  //加载 obj 文件
    cube: true,  //是否将模型缩放到单位1的尺寸范围内,默认为false
    center: true,  //模型是否居中,默认为false,设置为true则会移动模型位置使其内容居中
    shape3d: 'box',  //如果指定了shape3d名称,则HT将自动将加载解析后的所有材质模型构建成数组的方式,以该名称进行注册
    finishFunc: function(modelMap, array, rawS3){  //用于加载后的回调处理 
      if(modelMap){  
        device2 = createNode('box', floor1);  //创建一个节点,在第一层“地板”上
    device2.p3([x1-120, y1+13, z1+60]);  //设置这个节点坐标
    device2.s3(rawS3);  //设置这个节点大小
    createEdge(device1, device2);  //创建连线
    device3 = createNode('box', floor1);  
    device3.s3(rawS3);  
    device3.p3([x1+120, y1+13, z1+60]);  
    createEdge(device1, device3);  
      }  
    }  
});

Die drei Parameter in der Funktion „finishiFunc“ sind wie folgt definiert:

  • modelMap : Rufen Sie ht.Default.parseObj auf. Der Rückgabewert nach dem Parsen. Wenn das Laden oder Parsen fehlschlägt, ist der Rückgabewert leer

  • Array: ein Array, das aus allen Materialmodellen besteht

  • rawS3: Enthält die Originalgröße aller Modelle

Im Allgemeinen setzen wir in praktischen Anwendungen die Größe des Grundelements auf die Originalgröße des Modells.

Über „Computer“ befindet sich eine rote „Warnung“, dass eine dreidimensionale Drehung möglich ist, die auf der Funktion ht.Default.setShape3dModel basiert (HT für Web Modeling Manual http://www.hightopo.com). /guide.. . 3D-Modell, in ht gibt es viele gekapselte Modellierungsfunktionen, die grundlegenderen sind Kugel, Zylinder, Würfel usw. Hier verwende ich die Ringkonstruktionsmethode createRingModel, um den äußersten Ring der „Warnung“ zu generieren Der obere Teil des Ausrufezeichens ist die mit createSmoothSphereModel erstellte Kugel und der untere Teil des Ausrufezeichens ist der mit createSmoothCylinderModel erstellte Zylinder. Ich habe die gekapselte Funktion zunächst direkt im 3D-Modell verwendet, daher kannte ich die Parameter nicht Wofür wird es verwendet? Ich verstehe nicht, wie das 3D-Modell aufgebaut ist. Deshalb habe ich die vorherigen „Grundlagen des Modells“ noch einmal gelesen und festgestellt, dass das ursprüngliche 3D-Modell am häufigsten eine Oberfläche verwendet Grundlegend ist die dreieckige Fläche, und dann werden auch die komplexen Flächen aus mehreren dreieckigen Flächen gebildet und dann um eine bestimmte Achse gedreht. Verschiedene Achsen können unterschiedliche Formen erzeugen Informationen zu Farbe und Stil finden Sie im Web-Style-Handbuch von HT (http://www.hightopo.com/guide...). Wie Sie dieses 3D-Modell drehen, kapselt ht in der von mir aufgerufenen Methode addScheduleTask(Task). Die dritte Ebene von Task. Eine gekapselte Rotationsfunktion setRotation wird verwendet, um die Reihenfolge und Richtung der Drehung festzulegen und das zu drehende Objekt anzugeben. Das Folgende ist eine Methode zum Anpassen des 3D-Modells von „Warnung“ (Hinweis: Da das Modell In diesem Beispiel handelt es sich um eine benutzerdefinierte Kombination. Wenn Sie die Farbe des Gesamtmodells festlegen möchten, sollten Sie das Stilattribut „all.blend“ verwenden:

function createAlarm(device, formPane) {
    var ringModel = ht.Default.createRingModel([ 8, 1, 10, 1, 10, -1, 8, -1, 8, 1 ], null, null, false, false, 100);//根据xy平面的曲线,环绕一周形成3D模型。
    var sphereModel = ht.Default.createSmoothSphereModel(8, 8, 0, Math.PI*2, 0, Math.PI, 2);//构建光滑球体模型 
    var cylinderModel = ht.Default.createSmoothCylinderModel(8, true, true, 1, 2, 0, Math.PI*2, 8);//构建光滑圆柱体模型
    
    var alarmArr = [//组合模型 由三个模型ringModel、sphereModel、cylinderModel组合而成
        {
          shape3d: ringModel,//定义模型类型
          r3: [Math.PI/2, 0, 0],//设置旋转角度
          color: {//设置模型颜色
            func: 'style@all.blend',//数据绑定style样式中的all.blend属性,可通过data.s()获取和设置这个属性
          }
        },{
          shape3d: sphereModel,
          t3: [0, 4, 0],
          color: {
            func: 'style@all.blend',
          }
        },{
          shape3d: cylinderModel,
          t3: [0, -3, 0],
          color: {
            func: 'style@all.blend',
          }
        }
    ];
    ht.Default.setShape3dModel('alarm', {//注册自定义3D模型
      shape3d: alarmArr
    });

    var alarmTip = createNode('alarm', device);//创建shape3d为alarm的节点
    alarmTip.s3([2, 2, 2]);//设置节点大小
    alarmTip.p3(device.p3()[0], device.p3()[1]+60, device.p3()[2]);
    alarmTip.s('all.blend', 'red');//改变此属性可改变模型的颜色,因为模型创建的时候已经数据绑定了

    return alarmTip;
}

Als Nächstes sehen wir uns an, wie dies erstellt wird. Alarm“-Knoten „Flash“. Ich binde diese Animation direkt an den Knoten. Auf diese Weise kann die Animation direkt über den Knoten gesteuert werden. Wenn wir also das Alarmmodell oben erstellen, können wir die Animation direkt an den Knoten binden:

if(formPane){
    alarmNode.scaleFunc = function() {//设置大小变化动画
        var size = alarmNode.s3();//获取节点的大小
        if (size[0] === 2 && size[1] === 2 && size[2] === 2) alarmNode.s3([1, 1, 1]);
        else alarmNode.s3([2, 2, 2]);
        alarmNode.scaleTimer = setTimeout(alarmNode.scaleFunc, formPane.v('scaleInterval'));//设置动画
    }
    alarmNode.blinkFunc = function(){//设置闪烁的动画
        var color = alarmNode.s('all.blend');//获取节点的style样式
        if (color === 'red') alarmNode.s({'all.blend': 'yellow'});//如果节点颜色为红色,那么设置为黄色
        else alarmNode.s({'all.blend': 'red'});
        alarmNode.blinkTimer = setTimeout(alarmNode.blinkFunc, formPane.v('blinkInterval'));
    }
    alarmNode.rotateFunc = function() {//设置旋转动画
        alarmNode.setRotation(alarmNode.getRotation() + Math.PI/20);//获取节点当前的旋转角度,在这个旋转角度之上添加 Math.PI/20 个角度
        alarmNode.rotateTimer = setTimeout(alarmNode.rotateFunc, formPane.v('rotInterval'));
    }
}

Ich habe die obige Animation so eingestellt, dass sie über die Eigenschaften des Formularfensters die Geschwindigkeit des Knotenblinkens, die Animation blinkender Knoten usw. steuern kann. Lassen Sie uns hauptsächlich über die Implementierung dieser Funktion sprechen das Formular:

formPane.addRow([//向form表单面板上添加一行元素
    {
        checkBox: {//复选框
            label: 'Enable Blink',//复选框对应的文本内容
            selected: true,//设置选中复选框
            onValueChanged: function(){//复选框值变化时回调的函数
                var data = dataModel.getDataByTag('colorAlarm');//通过tag标签获取节点
                if (this.getValue()) {//获取复选框当前值true/false
                    data.blinkTimer = setTimeout(data.blinkFunc, formPane.v('blinkInterval'));//直接通过设置节点的blinkTimer来设置动画
                }
                else {
                    clearTimeout(data.blinkTimer);//清除动画
                }
            }
        }
    },
    {
        id: 'blinkInterval',//form可以通过getValue(简写为v)来获取这个item的值
        slider: {//设置了该属性后HT将根据属性值自动构建ht.widget.Slider对象,并保存在element属性上
            min: 0,//滑动条最小值
            max: 1000,//滑动条最大值
            step: 50,//滑动条步进
            value: 500,//当前滑动条的值
        }
    }
], [0.1, 0.1]);//设置这行的两个item元素的宽度小于1的值为比例

Lassen Sie uns zum Schluss über den Ballfluss in der 3D-Pipeline sprechen. Diese Funktion ist in der Tat sehr praktisch und der Effekt ist wirklich gut, ich möchte sie mit Ihnen teilen

首先,创建一条连线连接起始节点和结束节点并设置这个连线的样式,用 ht.Edge 可以将连线吸附在起始节点和结束节点上,这样移动这两个节点中的任意一个节点连线都会跟着节点移动的位置变化,非常方便:

var polyline = new ht.Edge(source, target);//创建连线
dataModel.add(polyline);//将连线添加进数据容器中
polyline.s({
    'edge.width': 5,//连线宽度
    'edge.type': 'points',//连线类型 为points时连线走向将由edge.points属性决定,用于绘制折线
    'edge.points': [//可设置类型为ht.List的{x:100, y:100}格式的点对象数组,当edge.type为points时起作用
        {x: source.getPosition3d()[0]+200, y: source.getPosition3d()[2], e: source.getPosition3d()[1]},
        {x: target.getPosition3d()[0]+400, y: target.getPosition3d()[2], e: target.getPosition3d()[1]}
    ],
    'edge.segments': [1, 4],//用于描述点连接样式,数组元素为整型值
    'shape3d': 'cylinder',//圆柱
    'shape3d.color': 'rgba(242, 200, 40, 0.4)',
    'shape3d.resolution': 30,//微分段数,可以决定曲线的平滑度
    'edge.source.t3': [20, 0, 0],//连线source端偏移,[tx, ty, tz]格式,默认为空
    'edge.target.t3': [20, 0, 0]//连线target端偏移,[tx, ty, tz]格式,默认为空
});

因为我们在创建连线的时候设置的 points 仅为曲线上的两个点,所以如果要获取曲线目前形成的点,是缺少 source 和 target 两个点的,我们重新设置一个数组,将这两个点添加进去,后面获取曲线上所有点时会用上:

var list = new ht.List();
list.push({x: source.getPosition3d()[0], y: source.getPosition3d()[2], e: source.getPosition3d()[1]});//向数组中添加source点
polyline.s('edge.points').each(function(item){//添加style属性中已设置的两个点
    list.push(item);
});
list.push({x: target.getPosition3d()[0], y: target.getPosition3d()[2], e: target.getPosition3d()[1]});//添加target点

然后创建一个在管线上滑动的小球节点,这是仅是设置节点,真正添加进数据容器 dataModel 中需要设置完小球的坐标时再添加,如果没有给节点设置位置就将节点添加进数据容器中,节点的初始位置就是 3D 场景的正中心 [0, 0, 0] 的位置。小球滑动的动画代码如下:

var ball = new ht.Node();//创建小球节点
ball.s({//设置小球节点的样式
    'shape3d': 'sphere',//设置小球的3d模型为球形
    'shape3d.color': 'rgba(40, 90, 240, 0.4)'//设置3d模型的颜色
});

var delta = 10, flag = 0;
setInterval(function(){
    flag++;
    var length = (polyline.a('total') || 0) % polyline.a('length') + delta;//小球当前走过的曲线长度
    var cache = ht.Default.getLineCacheInfo(list, polyline.s('edge.segments'));//获取曲线上的点的信息
    var lineLength = ht.Default.getLineLength(cache);//获取曲线的总长度
    polyline.a('length', lineLength - 50);//因为我设置了edge的t3(相当于2d中的offset),所以线段长度实际没有那么长
    var offset = ht.Default.getLineOffset(cache, length);//曲线根据曲线上点的信息的偏移量
    ball.setPosition3d(offset.point.x + 10, offset.point.y, offset.point.z);//设置节点的坐标
    polyline.a('total', length);
    if(flag === 1) dataModel.add(ball);//这时候节点已经有了坐标了,可以添加进数据容器中了
}, 10);

我们还可以看到第二层上有两个特殊的多边形“平行四边形”和“梯形”,平行四边形是靠 createParallelogramModel 模型函数,这个函数比较简单,createExtrusionModel(array, segments, top, bottom, resolution, repeatUVLength, tall, elevation),array 是你要形成的图形的坐标点,这边只是针对于 xz 轴上画的平面图形,segments 指的是如何连接这几个坐标点,可参考 HT for Web 形状手册(http://hightopo.com/guide/gui...),top 和 bottom 就是让你选择是否有顶部或者底部,resolution 微分段数,我们描绘一段曲线的时候可能只要确认几个个别的点然后在每两个点之间的连线上把它分成多个段,这样这条线段就会变得平滑,ht 为了用户能够轻松操作这些线段,就封装了这一个参数,repeatUVLength 默认为空,设置值后顶部和底部的贴图将根据制定长度值进行重复,tall 模型的高度,默认为 5,elevation 模型中心的 y 轴位置,默认值为 0,设置这个值可以使 xz 上的平面绕着 y 轴旋转。

底层的一个环形的效果是通过一个算法来实现的,环形得确认这个环形上有多少个元素,然后算每两个之间的角度,在通过 sin、cos 来计算每一个元素的位置,得出了如下代码:

names = ['设备2', '设备3', '设备4', '设备5', '设备6', '设备7', '设备8', '设备9'];  
names.forEach(function(name, index) {  
    x = 400, y = 200, angle = 45, r = 120;  
    x = x3 + Math.sin((2 * Math.PI / 360) * angle * index) * r;  
    y = z3 + Math.cos((2 * Math.PI / 360) * angle * index) * r;  
    device = createRect([x, y3 + 15, y], [w * 0.1, 15, h * 0.1], '', '', floor3);  
    createEdge(device5, device);  
});

相关推荐:

HTML5 网络拓扑图应用实例讲解

有向图之任务调度拓扑图介绍

关于网络拓扑的10篇文章推荐

Das obige ist der detaillierte Inhalt von3D-Netzwerktopologiediagramm von HTML5 WebG. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
H5 -Code verstehen: Die Grundlagen von HTML5H5 -Code verstehen: Die Grundlagen von HTML5Apr 17, 2025 am 12:08 AM

HTML5 ist eine Schlüsseltechnologie zum Aufbau moderner Webseiten und bietet viele neue Elemente und Funktionen. 1. HTML5 führt semantische Elemente wie usw. ein, die die Webseitenstruktur und die SEO verbessern. 2. Support Multimedia-Elemente und Einbetten von Medien ohne Plug-Ins. 3. Formulare verbessern neue Eingangstypen und Überprüfungseigenschaften und vereinfachen Sie den Überprüfungsprozess. 4. Bieten Sie Offline- und lokale Speicherfunktionen an, um die Leistung der Webseiten und die Benutzererfahrung zu verbessern.

H5 -Code: Best Practices für WebentwicklerH5 -Code: Best Practices für WebentwicklerApr 16, 2025 am 12:14 AM

Zu den Best Practices für den H5 -Code gehören: 1. Verwenden Sie korrekte DocType -Deklarationen und Zeichenkodierung; 2. Verwenden Sie semantische Tags; 3.. HTTP -Anfragen reduzieren; 4. Verwenden Sie asynchrone Laden; 5. Bilder optimieren. Diese Praktiken können die Effizienz, Wartbarkeit und Benutzererfahrung von Webseiten verbessern.

H5: Die Entwicklung von Webstandards und TechnologienH5: Die Entwicklung von Webstandards und TechnologienApr 15, 2025 am 12:12 AM

Webstandards und -technologien haben sich bisher aus HTML4, CSS2 und einfachem JavaScript entwickelt und haben erhebliche Entwicklungen erfahren. 1) HTML5 führt APIs wie Leinwand und Webstorage ein, die die Komplexität und Interaktivität von Webanwendungen verbessern. 2) CSS3 fügt Animations- und Übergangsfunktionen hinzu, um die Seite effektiver zu gestalten. 3) JavaScript verbessert die Entwicklungseffizienz und die Lesbarkeit der Code durch moderne Syntax von Node.js und ES6, wie z. B. Pfeilfunktionen und Klassen. Diese Änderungen haben die Entwicklung von Leistungsoptimierung und Best Practices von Webanwendungen gefördert.

Ist H5 eine Abkürzung für HTML5? Erforschen der DetailsIst H5 eine Abkürzung für HTML5? Erforschen der DetailsApr 14, 2025 am 12:05 AM

H5 ist nicht nur die Abkürzung von HTML5, sondern auch ein breiteres Ökosystem der modernen Webentwicklungstechnologie: 1. H5 enthält HTML5, CSS3, JavaScript und verwandte APIs und Technologien; 2. Es bietet eine reichhaltigere, interaktive und reibungslose Benutzererfahrung und kann nahtlos auf mehreren Geräten ausgeführt werden. 3. Mit dem H5 -Technologie -Stack können Sie reaktionsschnelle Webseiten und komplexe interaktive Funktionen erstellen.

H5 und HTML5: häufig verwendete Begriffe in der WebentwicklungH5 und HTML5: häufig verwendete Begriffe in der WebentwicklungApr 13, 2025 am 12:01 AM

H5 und HTML5 beziehen sich auf dasselbe, nämlich HTML5. HTML5 ist die fünfte Version von HTML, die neue Funktionen wie semantische Tags, Multimedia -Support, Leinwand und Grafiken, Offline -Speicher und lokaler Speicher bietet, die Ausdrucksfähigkeit und Interaktivität von Webseiten verbessert.

Worauf bezieht sich H5? Erforschen des KontextesWorauf bezieht sich H5? Erforschen des KontextesApr 12, 2025 am 12:03 AM

H5REFERSTOHTML5, ApivotaltechnologyInwebdevelopment.1) HTML5IntroducesNewelementsandapisrich, Dynamicwebapplications.2) ITSUPP ortsmultimediaWitHoutPlugins, BETHINGINGUSEREXPERICERCROSSDEVICES.3) SEMANTICELEMENTSIMPROVEPENTENTENTENTRUCTENTRUCTELUREANDSEO.4) H5'SRespo

H5: Tools, Frameworks und Best PracticesH5: Tools, Frameworks und Best PracticesApr 11, 2025 am 12:11 AM

Zu den Tools und Frameworks, die in der H5 -Entwicklung gemeistert werden müssen, gehören Vue.js, React und WebPack. 1.Vue.js eignet sich zum Erstellen von Benutzeroberflächen und unterstützt die Komponentenentwicklung. 2. Die Rendern des Seitenrenders über virtuelle DOM optimiert, geeignet für komplexe Anwendungen. 3.Webpack wird zur Modulverpackung und zur Optimierung der Ressourcenlast verwendet.

Das Erbe von HTML5: H5 in der Gegenwart verstehenDas Erbe von HTML5: H5 in der Gegenwart verstehenApr 10, 2025 am 09:28 AM

HTML5hassignificantlytransformedwebdevelopmentbyintroducingsemanticelements,enhancingmultimediasupport,andimprovingperformance.1)ItmadewebsitesmoreaccessibleandSEO-friendlywithsemanticelementslike,,and.2)HTML5introducednativeandtags,eliminatingthenee

See all articles

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat -Befehle und wie man sie benutzt
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Sicherer Prüfungsbrowser

Sicherer Prüfungsbrowser

Safe Exam Browser ist eine sichere Browserumgebung für die sichere Teilnahme an Online-Prüfungen. Diese Software verwandelt jeden Computer in einen sicheren Arbeitsplatz. Es kontrolliert den Zugriff auf alle Dienstprogramme und verhindert, dass Schüler nicht autorisierte Ressourcen nutzen.

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

MantisBT

MantisBT

Mantis ist ein einfach zu implementierendes webbasiertes Tool zur Fehlerverfolgung, das die Fehlerverfolgung von Produkten unterstützen soll. Es erfordert PHP, MySQL und einen Webserver. Schauen Sie sich unsere Demo- und Hosting-Services an.

VSCode Windows 64-Bit-Download

VSCode Windows 64-Bit-Download

Ein kostenloser und leistungsstarker IDE-Editor von Microsoft

WebStorm-Mac-Version

WebStorm-Mac-Version

Nützliche JavaScript-Entwicklungstools