ADN Open CIS
Сообщество программистов Autodesk в СНГ

09/08/2018

Создание разметки Pushpin по SVG

 

Пример IoT от моего коллеги Philippe очень впечетляет. Одной из особенностей является разметка pushpin, которая представляет собой датчик в модели.  Разметка построена SVG. 2 года назад, Philippe также создал блог о работе с разметкой SVG в Forge Viewer. Хотя рабочий процесс немного сложнее для некоторых клиентов, поскольку он включает в себя комплексные функции, результатом которых является отличная демонстрация.

Итак, я попытался изолировать основной раздел, чтобы сделать небольшой пример: когда пользователь нажимает на местоположение объекта, будет создана разметка pushpin. Хотя Forge Viewer 6.0 предоставляет расширение Pushpin, я думаю, что основная логика SVG также будет полезна в некоторых сценариях. 

Некоторые трюки для обмена:

  1. SVG содержится в svg элементе, а svg обернут div DOM.
  2. Графика SVG просчитывается библиотекой JavaScript svg-snap, благодаря которой мы можем динамически манипулировать графикой. В моем примере, радиус круга является фиксированным.
  3. Поскольку SVG отображается в пространстве экрана в 2D-координации, когда камера Forge Viewer изменяется, нам необходимо обновить местоположение SVG соответственно в случае события CAMERA_CHANGE_EVENT. Forge Viewer предоставляет метод worldToClient, который может преобразовать позицию 3D-модели в координаты2D-экрана.
  4. В CAMERA_CHANGE_EVENT, исходная позиция 3D-модели будет недоступна.  В моем примере я прикрепляю 3D-данные к SVG DOM с помощью словаря DOM.data.
  5. Чтобы получить выбранную позицию объекта, образец использует viewer.impl.hitTest, который может обеспечить точку пересечения и dbid объекта.

Код - JavaScript: [Выделить]
  1. //предположим, что _viewer3D доступен
  2. var _viewer3D;
  3.  
  4. function init(){
  5.  
  6.   //делегировать событие щелчка мыши
  7.   $(_viewer3D.container).bind("click", onMouseClick);
  8.  
  9.   // делегировать событие CAMERA_CHANGE_EVENT
  10.   _viewer3D.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT, function(rt){ 
  11.  
  12.     // находим все разметки pushpin
  13.     var $eles = $("div[id^='mymk']");
  14.     var DOMeles = $eles.get();
  15.  
  16.     for(var index in DOMeles){
  17.       
  18.       // получить каждый элемент DOM
  19.       var DOMEle = DOMeles[index];
  20.       var divEle = $('#' + DOMEle.id);
  21.       // выходим из трехмерной системы координат
  22.        var val = divEle.data('3DData');
  23.        var pushpinModelPt = JSON.parse(val);
  24.        // получаем обновленную точку экрана
  25.        var screenpoint = _viewer3D.worldToClient(new THREE.Vector3(
  26.         pushpinModelPt.x,
  27.         pushpinModelPt.y,
  28.         pushpinModelPt.z,));
  29.         // обновляем позицию SVG.
  30.         divEle.css({
  31.             'left': screenpoint.x - pushpinModelPt.rad*2,
  32.             'top': screenpoint.y - pushpinModelPt.rad
  33.             });
  34.       }
  35.   }); 
  36. } 
  37.  
  38. function onMouseClick (event) {
  39.  
  40.     var screenPoint = {
  41.         x: event.clientX,
  42.         y: event.clientY
  43.     };
  44.  
  45.     // получаем выбранную трехмерную позицию объекта
  46.     var hitTest = _viewer3D.impl.hitTest(screenPoint.x,screenPoint.y,true);
  47.     if(hitTest)
  48.     { 
  49.        drawPushpin({x:hitTest1.intersectPoint.x,
  50.                     y:hitTest1.intersectPoint.y,
  51.                     z:hitTest1.intersectPoint.z});
  52.     }
  53. }
  54.  
  55. // генерируем случайный идентификатор для каждой разметки pushpin
  56. function makeid() {
  57.   var text = "";
  58.   var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  59.  
  60.   for( var i=0; i < 5; i++ )
  61.   text += possible.charAt(Math.floor(Math.random() * possible.length));
  62.  
  63.   return text;
  64.   }
  65.  
  66. function drawPushpin(pushpinModelPt){ 
  67.  
  68.   // конвертирование 3D-позиции в координаты 2D-экрана
  69.   var screenpoint = _viewer3D.worldToClient(
  70.                     new THREE.Vector3(pushpinModelPt.x,
  71.                                       pushpinModelPt.y,
  72.                                       pushpinModelPt.z,));
  73.  
  74.     // создаем контейнер div
  75.     var randomId = makeid();
  76.     var htmlMarker = '<div id="mymk' + randomId + '"></div>';
  77.     var parent = _viewer3D.container
  78.     $(parent).append(htmlMarker);
  79.     $('#mymk'+randomId ).css({
  80.         'pointer-events': 'none',
  81.         'width': '20px',
  82.         'height': '20px',
  83.         'position': 'absolute',
  84.         'overflow': 'visible'
  85.         });
  86.      
  87.     // создаем элемент svg и нарисуем круг
  88.       $('#mymk'+randomId).append('<svg id="mysvg'+randomId+ '"></svg>')
  89.       var snap = Snap($('#mysvg'+randomId)[0]);
  90.       var rad = 12;
  91.       var circle = snap.paper.circle(14, 14, rad);
  92.       circle.attr({
  93.           fill: "#FF8888",
  94.           fillOpacity: 0.6,
  95.           stroke: "#FF0000",
  96.           strokeWidth: 3
  97.       });
  98.  
  99.       // установить положение SVG
  100.       // настраиваем, чтобы центр окружности представлял собой положение точки щелчка
  101.       var $container = $('#mymk'+randomId);
  102.       $container.css({
  103.           'left': screenpoint.x - rad*2,
  104.           'top': screenpoint.y - rad
  105.       });
  106.      
  107.       // сохраняем данные 3D-точки в DOM
  108.       var div = $('#mymk'+randomId);
  109.       // добавление информации о радиусе с помощью трехмерных данных
  110.       pushpinModelPt.radius = rad;
  111.       var storeData = JSON.stringify(pushpinModelPt);
  112.       div.data('3DData', storeData);
  113. }
  114.  
  115. init();

Источник: https://forge.autodesk.com/blog/create-pushpin-markup-svg

 

Автор перевода: Дмитрий Емельянов

Обсуждение: http://adn-cis.org/forum/index.php?topic=

Опубликовано 09.08.2018
Отредактировано 09.08.2018 в 17:29:28