テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

序文

風のエネルギーは開発中の一種のクリーンなエネルギーであり、無尽蔵で無尽蔵です。もちろん、ウインドファームを建設する際には、気象条件と社会的自然条件を最初に考慮する必要があります。近年、中国のオフショアおよびオンショア風力発電は急速に発展しています。海の水と土地は、私たちの風力発電に優れた地質学的保証を提供します。私たちの風力に無尽蔵のエネルギーを提供するのはこれらの場所です。現在、私たちはこれらの分野を探求するために一生懸命取り組んでいます。

今日は共有の記事では、私が使用 することによって構築された可視化システムのWeb用のHT の製品Hightopo風力発電所の全体的な流れを実現し、誰もが完全な風力発電プレビューシステムを参照することができました。

大まかなプロセス

以下はプロジェクト全体のフローチャートです。ホームページからサイト配布ページと集中管理ページに入ることができます。

サイト配布ページには、陸風空港と沖合風空港の2つの異なる3Dシーンも含まれています。2つの3Dウィンドフィールドをクリックすると、最終的に3Dウィンドタービンシーンに入ります。

テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

 

実装分析:

ホームページ:

1.ワールドマップ効果

テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

動的操作プレビューアドレス:https//www.hightopo.com/demos/index.html

2.チャイナマップ効果

テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

 

3.シティマップ効果

テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

 

一元化されたコントロールセンターページ(アニメーション効果なし):

テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

 

フィールド配布ページ(アニメーション効果なし):

テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

 

ランドウィンド空港:

テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

 

ハイフェン空港:

テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

 

コード

ホームページの地球には、世界地図、中国地図、都市地図の3つの視点があります。各状態をクリックすると、カメラは対応する位置に移動します。その前に、対応する中心 と 目を事前に保存する必要があり ます。

 データを提供するための専用の新しいdata.jsファイルを作成することをお 勧めします。

関連する疑似コードは次のとおりです。

// 记录位置
var cameraLocations = {
    earth: {
        eye: [-73, 448, 2225],
        center: [0, 0, 0]
    },

    china: {
        eye: [-91, 476, 916],
        center: [0, 0, 0]
    },

    tsankiang: {
        eye: [35, 241, 593],
        center: [0, 0, 0]
    }
};

さて、データで。次にイベントを聞く必要があります。ボタンをクリックするか、強調表示された領域(ワールドマップをクリックのみ)をクリックして、中国のマップパースペクティブに入ることができます。

テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

 

これらの2つのノードを最初に取得してから、それらのクリックイベントに対して同じ処理を実行できます。ただし、このアプローチは最適化して、新しい考え方に置き換えることができると思います。

最初にイベントをフィルタリングできます。2つの配列を作成します。1つはclickやonEnterなどの 実行可能なイベントを保持し、もう1つは イベントをトリガーできるすべてのノードを保持します。これは私たちが維持するのに役立ちますが、構造をより明確にすることもできます。

次の図では、現在のノードにイベント権限がない場合、または現在のイベント自体に権限がない場合、そのノードが除外されることがわかります。すべてが正しく返される場合は、対応するイベントを実行します。

テクノロジーフロンティア:HTML5WebGLに基づく3Dウィンドファーム

 

現在実行しているノードが要件を満たしている限り、イベント(現在実行中のイベント)とタグ(ノードタグ)を実行関数nodeEventに渡して実行します。このようにして、無効なイベントやノードを処理するためにリソースが無駄になることはありません。

次にnodeEvent がそれをどのように処理するかを見てみましょう 

関連する疑似コードは次のとおりです。

/**
 * 气泡事件
 * @param { string } event 当前事件
 * @param { string } propertyName 当前节点标签
 */
bubblesEvent(event, propertyName) {
    var dm = this.dm
    var account = dm.getDataByTag('account')
    var currentNode = dm.getDataByTag(propertyName)
    var self = this

    var clickData = function() {
        // 执行清除动作
        self.clearAction()
    }

    var onEnter = function() {
       // do something
    }

    var onLeave = function() {
    // do something
    }

    var allEvent = { clickData, onEnter, onLeave }

    allEvent[event] && allEvent[event]()
}

ご覧のとおり、propertyName(ノードラベル) 文字列連結を使用してメソッド名を形成できます たとえば、現在取得されているノードラベルは バブルであり、 this [`$ {properName} Event`]の 後に 、メソッドthis ['bubblesEvent'] が取得されます。もちろん、この方法は事前に定義されています。

特定のノードメソッドで、対応するイベント関数を作成しました。渡されたイベント に従って 、対応するメソッドがあるかどうかを判別します。存在する場合は実行し、存在しない場合はfalseを返し ます 。これの利点は、デカップリング、単純な構造、および問題の迅速な配置です。

しかし、考えてみると、世界地図と中国地図をクリックすると、機能は似ています!それらをマージできれば、はるかに便利になります!コードを変換してみましょう。

関連する疑似コードは次のとおりです。

/**
  * 执行节点事件
  */
function nodeEvent(event, propertyName) {
    // 过滤是否有可以合并的事件
    var filterEvents = function(propertyName) {
        var isCombine = false
     var self = this
        if (['earth', 'china'].includes(propertyName)) {
            self.changeCameraLocaltions(event, propertyName)
            isCombine = true
        }

        return !isCombine
    }
   var eventFun = this[`${propertyName}Event`]
   // 执行对应的节点事件
   filterEvents(propertyName) &&
   eventFun &&
   eventFun(event, propertyName)
}

現在のイベントをマージできるかどうかを事前に判断し、マージできる場合はfalseを返し、次のコードを実行しなくなった後、独自の関数を実行します。

このとき、対応するノードラベルを介してdata.jsのcameraLocations変数から対応する中心と目を取得できます。

移動カメラアニメーションは 、gvmoveCamera メソッドを使用します。 このメソッドは eye(カメラ)center(ターゲット)、およびanimConfig(アニメーション構成)の3つのパラメーターを受け入れます。次に、現在のアニメーションを  globalAnimのmoveCameraAnim プロパティに戻し、クリーンアップ を容易にします。

次のステップはページを切り替えることですが、これには細心の注意が必要です。特定の属性がクリアされないと、メモリリークなどの問題が発生し、パフォーマンスが低下します。ページがフリーズします!

したがって、データモデルのクリア専用の関数clearActionが必要 です。すべてのアニメーションオブジェクトをオブジェクトまたは配列に配置する必要があります。これは、ページを切り替えるときのクリーンアップに便利です。

関連する疑似コードは次のとおりです。

/**
 * 清除动作
 */
clearAction(index) {
    var { dm, gv } = this
    var { g3d, d3d } = window

    allListener.mi3d && g3d.umi(allListener.mi3d)
    allListener.mi2d && gv.umi(allListener.mi2d)
    dm.removeScheduleTask(this.schedule)

    dm && dm.clear()
    d3d && d3d.clear()

    window.d3d = null
    window.dm = null

    for (var i in globalAnim) {
        globalAnim[i] && globalAnim[i].pause()
        globalAnim[i] = null
    }

    // 清除对应的 3D 图纸
    ht.Default.removeHTML(g3d)

    gv.addToDOM()
    ht.Default.xhrLoad(`displays/HT-project_2019/风电/${index}.json`, function (text) {
        let json = ht.Default.parse(text)
        gv.deserialize(json, function(json, dm2, gv2, datas) {
            if (json.title) document.title = json.title

            if (json.a['json.background']) {
                let bgJSON = json.a['json.background']
                if (bgJSON.indexOf('scenes') === 0) {
                    var bgG3d

                    if (g3d) {
                        bgG3d = g3d
                    } else {
                        bgG3d = new ht.graph3d.Graph3dView()
                    }

                    var bgG3dStyle = bgG3d.getView()
                    bgG3dStyle.className = index === 1 ? '' : index === 3 ? 'land' : 'offshore'

                    bgG3d.deserialize(bgJSON, function(json, dm3, gv3, datas) {
                        init3d(dm3, gv3)
                    })

                    bgG3d.addToDOM()
                    gv.addToDOM(bgG3dStyle)
                }
                gv.handleScroll = function () {}
            }

            init2d(dm2, gv2)
        })
    })
}

まず、dm(データモデル) と gv(図面) クリアする必要があり ます。また、注意:mi(監視機能)Schedule(スケジュールされたタスク) は、Removeの 前にdm.clear()する 必要があり ます。すべてのアニメーションはstop() 操作を実行して から、その値をnullに設定し ます 。ここで 、stopが実行された後、finishFunc コールバック関数が1回呼び出される ことに注意してください 

2D図面に3D背景が含まれている場合、3Dインスタンスがすでに存在するかどうかを判断する必要があり、存在する場合は、再度作成する必要はありません。webGL アプリケーションのメモリリークについて 知りたい

2つの3Dシーンに入るときは、最初のgifのようなオープニングアニメーションが必要です。したがって、 定義したcameraLocationsに 2つのオープニングアニメーションの中心 と 保存 する必要があり ます。

offshoreStart、offshoreEnd、landStart、およびlandEndは、オフショアおよびオンショア発電所の開始位置と終了位置を示します。

現在の負荷がオフショア発電所であるかオンショア発電所であるかを判断する必要があります。対応する図面をロードするときにclassNameを追加でき ます。

関数clearAction で インデックスパラメータを定義しました。陸上発電所をクリックすると、番号3が渡され、オフショア発電所の場合は、番号4になります。

たとえば、陸上の発電所に負荷をかける必要がある場合、g3d.className = index === 3? 'Land': 'offshore'と 判断して className追加でき ます。

次に、initで初期化判定を実行します。

関連する疑似コードは次のとおりです。

function init() {
    var className = g3d.getView().className

    // 执行单独的事件
    this.selfAnimStart(className)

    this.initData()

    // 监听事件
    this.monitor()
}

対応するclassNameを取得し、対応 するタイプを渡して、対応する初期化イベントを実行し、定義したmoveCameraAnim 関数を使用してカメラを アニメーション化します。

関連する疑似コードは次のとおりです。

/**
  * 不同风电场的开场动画
  */
function selfAnimStart(type) {
    var gv = this.gv
    var { eye, center } = cameraLocations[`${type}End`]
    var config = {
            duration: 3000,
            eye,
            center,
         }

    this.moveCameraAnim(gv, config)
}

総括する

このプロジェクトを終えた後、私は多くの成長と洞察を得ました。テクノロジーの急速な成長のための良い方法は、常に詳細を掘り下げることです。このプロジェクトは芸術作品であり、満足するまで継続的に磨く必要があります。微妙な点はすべて、背後のパフォーマンスに影響します。したがって、私たちは職人の精神ですべてを行う必要があります。

もちろん、一部のパートナーが産業用インターネット分野をあえて探求できることも願っています。これ以上のことを達成できます。これには、この分野にもっと楽しく実用的なデモを追加するための想像力が必要です。また、産業分野で多くの知識を学びます。

おすすめ

転載: blog.csdn.net/iotopo/article/details/108193597
おすすめ