{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["tabs","tab"]},"type":"markdown"},"seo":{"title":"Lazy Loading","description":"Accelerate E&P application development and protect your innovation by consuming our Data and Domain APIs / Platform APIs.","lang":"en-US","meta":[{"name":"robots","content":"noindex"}],"llmstxt":{"hide":true,"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"lazy-loading","__idx":0},"children":["Lazy Loading"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This tutorial demonstrates how to share single well template for different well tracks and instantiate it when needed, to continue to work with real instance when needed."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This tutorial assumes familiarity with the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/WellLog/MultiWell/ProxyTrack/proxyTrack"},"children":["Proxy track tutorial"]}," tutorials."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"create-proxy-track","__idx":1},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/WellLog/MultiWell/LazyLoading/lazyLoading#createProxyTrack"},"children":["#"]}," Create Proxy Track"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In the next step, create proxy well track and provide created template as prototype."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"result","__idx":2},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/WellLog/MultiWell/LazyLoading/lazyLoading#result"},"children":["#"]}," Result"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This WellLog–Multi Well Correlation widget can display well tracks and correlation tracks between them. A Well Track can have the different set of tracks and curves, which is named as a template. Often the same template is used for all wells in the display to see correlation between the different wells. In this case usage of a normal ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["WellTrack"]}," cannot be efficient for big amount of wells, because it has a copy of tracks and curves and the own set of tools. In this case it is better to use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ProxyWellTrack"]}," for read only displays."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"main","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"import { obfuscate } from \"@int/geotoolkit/lib.js\";\nimport { MultiWellWidget } from \"@int/geotoolkit/welllog/multiwell/MultiWellWidget.ts\";\nimport { ProxyTrackActivationTool } from \"@int/geotoolkit/welllog/multiwell/tools/ProxyTrackActivationTool.ts\";\nimport { Range } from \"@int/geotoolkit/util/Range.ts\";\nimport { TrackType as MultiWellTrackType } from \"@int/geotoolkit/welllog/multiwell/TrackType.ts\";\nimport { TrackType as WellLogTrackType } from \"@int/geotoolkit/welllog/TrackType.ts\";\nimport { KnownColors } from \"@int/geotoolkit/util/ColorUtil.ts\";\nimport { MathUtil } from \"@int/geotoolkit/util/MathUtil.ts\";\nimport { LogCurve } from \"@int/geotoolkit/welllog/LogCurve.ts\";\nimport { LineStyle } from \"@int/geotoolkit/attributes/LineStyle.ts\";\nimport { LogMarker } from \"@int/geotoolkit/welllog/LogMarker.ts\";\nimport { AlignmentStyle, TextStyle } from \"@int/geotoolkit/attributes/TextStyle.ts\";\nimport { AnchorType } from \"@int/geotoolkit/util/AnchorType.ts\";\nimport { CorrelationMarker } from \"@int/geotoolkit/welllog/multiwell/correlation/CorrelationMarker.ts\";\nimport { Plot } from \"@int/geotoolkit/plot/Plot.ts\";\nimport { LogData } from \"@int/geotoolkit/welllog/data/LogData.ts\";\nimport { DataBinding } from \"@int/geotoolkit/data/DataBinding.ts\";\nimport { DataSource } from \"@int/geotoolkit/data/DataSource.ts\";\nimport { DataBindingRegistry } from \"@int/geotoolkit/data/DataBindingRegistry.ts\";\nimport { Events as ProxyWellTrackEvents } from \"@int/geotoolkit/welllog/multiwell/ProxyWellTrack.ts\";\nimport { getCurvesData } from \"/src/code/WellLog/MultiWell/data/curves.ts\";\nimport { Node, StateChanges } from \"@int/geotoolkit/scene/Node.ts\";\nimport { ResponsiveStyle } from \"@int/geotoolkit/responsive/ResponsiveStyle.ts\";\nconst curvesData = getCurvesData();\nconst bindingFunctions = [];\nclass CurveBinding extends DataBinding {\n  constructor() {\n    super();\n  }\n  accept(node) {\n    return node instanceof LogCurve;\n  }\n  bind(curve, data) {\n    if (data == null) {\n      return;\n    }\n    const id = curve.getName();\n    const source = data.getCurveSource(id);\n    if (source != null) {\n      const limits = MathUtil.calculateNeatLimits(source.getMinValue(), source.getMaxValue());\n      if (curve.isCustomLimits() === true) {\n        curve.setData(source, false, true);\n      } else {\n        curve.setData(source, true, true).setNormalizationLimits(limits.getLow(), limits.getHigh());\n      }\n    }\n  }\n  unbind(curve, data) {\n  }\n}\nobfuscate(CurveBinding);\nclass LogDataSource extends DataSource {\n  constructor(startDepth) {\n    super();\n    this._sources = {};\n    this._startDepth = startDepth;\n    this._step = 10;\n  }\n  getCurveSource(curveMnemonic) {\n    if (this._sources[curveMnemonic]) {\n      return this._sources[curveMnemonic];\n    }\n    const data = new LogData(curveMnemonic);\n    const depths = [];\n    const values = [];\n    const curveData = getCurveData(curveMnemonic);\n    const amountOfPoints = curveData.length;\n    for (let i = 0; i < amountOfPoints; i++) {\n      depths.push(i * this._step + this._startDepth);\n      values.push(curveData[i]);\n    }\n    data.setValues(depths, values);\n    this._sources[curveMnemonic] = data;\n    return data;\n  }\n}\nobfuscate(LogDataSource);\nfunction getCurveData(curveMnemonic) {\n  const curveNames = curvesData.curveNames;\n  const curveData = curvesData.curveData;\n  for (let i = 0; i < curveNames.length; i++) {\n    if (curveNames[i] === curveMnemonic)\n      return curveData[i];\n  }\n  return null;\n}\nfunction createCorrelation(widget, width, wells) {\n  const correlation = widget.createTrack(MultiWellTrackType.CorrelationTrack, {\n    \"width\": width\n  });\n  wells.push(correlation);\n  return correlation;\n}\nlet _wellIndex = 1;\nfunction createWell(widget, positions, depthrange, template, wells) {\n  const title = \"Well \" + _wellIndex++;\n  const well = widget.createTrack(MultiWellTrackType.ProxyTrack, {\n    \"range\": positions,\n    \"welllog\": {\n      \"range\": depthrange\n    },\n    \"width\": template.getLayoutStyle().getWidth(),\n    \"height\": template.getLayoutStyle().getHeight(),\n    \"prototype\": {\n      \"template\": template\n    },\n    \"tools\": {\n      \"navigation\": true\n    },\n    \"title\": title,\n    \"name\": title\n  }).on(ProxyWellTrackEvents.Mount, (eventType, sender) => {\n    const data = new LogDataSource(depthrange.getLow());\n    sender.setData(data);\n  });\n  wells.push(well);\n  return well;\n}\nfunction getRules() {\n  const EPSILON = 1e-9;\n  return [\n    {\n      condition: function(node) {\n        const transform = node.getSceneTransform();\n        return Math.abs(transform.getScaleX() + EPSILON) < 1;\n      },\n      restore: false,\n      css: `\n                *[cssclass=\"INDEX_TRACK\"] {\n                   visible: false;\n                }\n                .geotoolkit.welllog.header.LogVisualHeader {\n                   visible: false;\n                }\n                .geotoolkit.welllog.multiwell.WellTrackVisualHeader {\n                   visible: true;\n                }\n                *[cssclass=\"horizontalGrid\"] {\n                   visible: false;\n                }\n                *[cssclass=\"verticalGrid\"] {\n                   visible: false;\n                }\n                .geotoolkit.welllog.LogTrack {\n                   border-visible: true;\n                }\n                .geotoolkit.welllog.LogMarker {\n                   visiblenamelabel: false;\n                   visibledepthlabel: false;\n                }\n            `\n    },\n    {\n      condition: function(node) {\n        const transform = node.getSceneTransform();\n        return Math.abs(transform.getScaleX() + EPSILON) >= 1;\n      },\n      restore: false,\n      css: `\n                *[cssclass=\"INDEX_TRACK\"] {\n                   visible: true;\n                }\n                .geotoolkit.welllog.header.LogVisualHeader {\n                   visible: true;\n                }\n                .geotoolkit.welllog.multiwell.WellTrackVisualHeader {\n                   visible: true;\n                }\n                *[cssclass=\"horizontalGrid\"] {\n                   visible: true;\n                }\n                *[cssclass=\"verticalGrid\"] {\n                   visible: true;\n                }\n                .geotoolkit.welllog.LogTrack {\n                   border-visible: true;\n                }\n                .geotoolkit.welllog.LogMarker {\n                   visiblenamelabel: true;\n                   visibledepthlabel: true;\n                }\n            `\n    }\n  ];\n}\nfunction setLevelOfDetails(widget, template) {\n  widget.getTrackContainer().setResponsiveStyle(new ResponsiveStyle({\n    \"rules\": getRules(),\n    \"target\": widget,\n    \"start\": function() {\n      Node.enableSceneGraphNotification(false);\n    },\n    \"end\": function() {\n      Node.enableSceneGraphNotification(true);\n      template.updateState(void 0, StateChanges.Rebuild);\n      widget.updateState(void 0, StateChanges.Rebuild);\n      widget.getTrackContainer().updateLayout();\n    }\n  }));\n  return widget;\n}\nfunction createWidget() {\n  const widget = new MultiWellWidget({\n    \"tools\": {\n      \"cursortracking\": {\n        \"tooltip\": {\n          \"enabled\": true\n        }\n      }\n    }\n  });\n  widget.getTool().insert(0, new ProxyTrackActivationTool(widget));\n  const template = createTemplate(widget);\n  const wells = [];\n  const bindingFunc = new CurveBinding();\n  bindingFunctions.push(bindingFunc);\n  const dataBinding = DataBindingRegistry.getInstance();\n  dataBinding.add(bindingFunc);\n  widget.setDataBinding(dataBinding);\n  for (let i = 0; i < 333; i++) {\n    let correlation3 = null;\n    if (i !== 0) {\n      correlation3 = createCorrelation(widget, 50, wells);\n    }\n    const well1 = createWell(widget, new Range(0, 500), new Range(4500, 5e3), template, wells);\n    addTops(well1, \"Tarbert\", 4750, KnownColors.DarkRed);\n    if (i !== 0) {\n      addTopsCorrelation(correlation3, 4800, 4750, KnownColors.DarkRed);\n    }\n    const correlation1 = createCorrelation(widget, 50, wells);\n    const well2 = createWell(widget, new Range(50, 300), new Range(2500, 5e3), template, wells);\n    addTops(well2, \"Tarbert\", 3e3, KnownColors.DarkRed);\n    const correlation2 = createCorrelation(widget, 50, wells);\n    const well3 = createWell(widget, new Range(25, 400), new Range(4700, 5e3), template, wells);\n    addTops(well3, \"Tarbert\", 4800, KnownColors.DarkRed);\n    addTopsCorrelation(correlation1, 4750, 3e3, KnownColors.DarkRed);\n    addTopsCorrelation(correlation2, 3e3, 4800, KnownColors.DarkRed);\n  }\n  widget.addTrack(wells);\n  setLevelOfDetails(widget, template);\n  return widget;\n}\nfunction createTemplate(widget) {\n  const well = widget.createTrack(MultiWellTrackType.WellTrack, {\n    \"welllog\": {\n      \"range\": new Range(4700, 5e3)\n    }\n  });\n  well.addTrack(WellLogTrackType.IndexTrack);\n  well.addTrack(WellLogTrackType.LinearTrack).addChild([\n    createEmptyCurve(\"GR\").setLineStyle(KnownColors.Green),\n    createEmptyCurve(\"CALI\").setLineStyle(KnownColors.Orange)\n  ]);\n  return well;\n}\nfunction createEmptyCurve(name) {\n  return new LogCurve().setName(name);\n}\nfunction addTops(well, name, depth, color) {\n  const top = new LogMarker(depth);\n  top.setLineStyle(LineStyle.fromObject({ \"color\": color }));\n  top.setTextStyle(TextStyle.fromObject({\n    \"color\": color,\n    \"alignment\": AlignmentStyle.Left,\n    \"font\": \"12px sans-serif\"\n  }));\n  top.setNameLabel(name);\n  top.setNameLabelPosition(AnchorType.TopCenter);\n  top.setDepthLabel(depth + \"\");\n  top.setDepthLabelPosition(AnchorType.BottomCenter);\n  well.getMarkerLayer().addChild(top);\n}\nfunction addTopsCorrelation(track, leftDepth, rightDepth, color) {\n  track.addChild(new CorrelationMarker({\n    \"linestyle\": {\n      \"color\": color,\n      \"width\": 2,\n      \"pixelsnapmode\": { \"x\": true, \"y\": true }\n    },\n    \"leftdepth\": leftDepth,\n    \"rightdepth\": rightDepth\n  }));\n}\nfunction createScene(canvas) {\n  const widget = createWidget();\n  const plot = new Plot({\n    \"canvaselement\": canvas,\n    \"root\": widget\n  });\n  widget.setHeaderHeight(\"auto\");\n  return {\n    plot,\n    widget\n  };\n}\nfunction dispose() {\n  bindingFunctions.forEach((bindingFunc) => DataBindingRegistry.getInstance().remove(bindingFunc));\n}\nexport { createScene, dispose };\n\ncreateScene(document.querySelector('[ref=\"plot\"]'));\n\n","lang":"ts"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"css","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"css","header":{"controls":{"copy":{}}},"source":"\n.cg-tooltip-holder {\n  position: relative;\n}\n\n.cg-tooltip {\n  position: absolute;\n  display: block;\n  padding: 2px 12px 3px 7px;\n  overflow: visible !important;\n  font-family: Roboto, Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  background: white !important;\n  opacity: 0.9;\n  color: #333333;\n  border: solid 1px gray;\n  border-radius: 5px;\n  text-align: left;\n  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n  border-radius: 5px;\n  margin: 0 !important;\n  z-index: 10000;\n  max-width: 400px;\n  text-wrap: normal !important;\n  white-space: normal !important;\n}\n/* Default setting for tooltip */\n.cg-tooltip-container {\n  position: absolute;\n  display: block;\n  overflow: visible !important;\n  font-family: Roboto, Helvetica, Arial, sans-serif;\n  font-size: 12px;\n  padding: 3px 7px;\n  background: #f7f7f7;\n  color: #333333;\n  border: 1px solid #938e8e;\n  opacity: 0.8;\n  text-align: left;\n  box-shadow: 3px 3px 10px #888;\n  margin: 0 !important;\n  z-index: 10000;\n  max-width: 400px;\n  text-wrap: normal !important;\n  white-space: normal !important;\n  user-select: none;\n}\n@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n  .cg-tooltip-container {\n    border-radius: 0;\n  }\n}\n/* Default left arrow for tooltip */\n.cg-tooltip-arrow-left::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 0;\n  top: 50%;\n  border: 5px solid transparent;\n  border-left: 0;\n  border-right: 5px solid  #938e8e;\n  transform: translate(calc(-100%), -50%);\n}\n.cg-tooltip-arrow-left::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 0;\n  top: 50%;\n  border: 4px solid transparent;\n  border-left: 0;\n  border-right: 4px solid #f7f7f7;\n  transform: translate(calc(-100%), -50%);\n}\n/* Default top arrow for tooltip */\n.cg-tooltip-arrow-top::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  top: 0;\n  border: 5px solid transparent;\n  border-top: 0;\n  border-bottom: 5px solid #938e8e;\n  transform: translate(-50%, -100%);\n}\n.cg-tooltip-arrow-top::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  top: 0;\n  border: 4px solid transparent;\n  border-top: 0;\n  border-bottom: 4px solid #f7f7f7;\n  transform: translate(-50%, -100%);\n}\n/* Default right arrow for tooltip */\n.cg-tooltip-arrow-right::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  right: 0;\n  top: 50%;\n  border: 5px solid transparent;\n  border-right: 0;\n  border-left: 5px solid #938e8e;\n  transform: translate(100%, -50%);\n}\n.cg-tooltip-arrow-right::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  right: 0;\n  top: 50%;\n  border: 4px solid transparent;\n  border-right: 0;\n  border-left: 4px solid #f7f7f7;\n  transform: translate(100%, -50%);\n}\n/* Default bottom arrow for tooltip */\n.cg-tooltip-arrow-bottom::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  bottom: 0px;\n  border: 5px solid transparent;\n  border-bottom: 0;\n  border-top: 5px solid #938e8e;\n  transform: translate(-50%, 100%);\n  z-index: 10000;\n}\n.cg-tooltip-arrow-bottom::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  bottom: 0;\n  border: 4px solid transparent;\n  border-bottom: 0;\n  border-top: 4px solid #f7f7f7;\n  transform: translate(-50%, 100%);\n  z-index: 10000;\n}\n/* Tooltip item name */\n/* Tooltip item value */\n/* .cg-tooltip-item-value */\n/* Tooltip item value */\n.cg-tooltip-item-unit {\n  text-transform: none;\n}\n\n.cg-tooltip-item-name {\n    text-transform: capitalize;\n    white-space: nowrap;\n    vertical-align: middle;\n    font-size: 13px;\n}\n.cg-tooltip-row {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  white-space: pre-wrap;\n  font-size: 12px;\n  line-height: 100%;\n  margin: 1px 0;\n}\n.cg-tooltip-title {\n  font-size: 13px;\n  height: 14px;\n  text-transform: capitalize;\n}\n.cg-tooltip-title .cg-tooltip-symbol {\n  margin-right: 0 !important;\n}\n.cg-tooltip-title-name {\n  vertical-align: middle;\n}\n.cg-tooltip-row + .cg-tooltip-row {\n  margin-top: 4px;\n}\n.cg-tooltip-row.cg-tooltip-title + .cg-tooltip-row {\n  margin-top: 5px;\n}\n.cg-tooltip-item-value + .cg-tooltip-item-unit {\n    margin-left: 1px;\n}\n/* Tooltip symbol */\n.cg-tooltip-symbol-cell {\n  display: inline-flex;\n  min-width: 13px; /* 10px size + 3px margin */\n}\n.cg-tooltip-symbol {\n  margin-right: 3px;\n  background-color: transparent;\n  display: block;\n}\n.cg-tooltip-symbol > img {\n  display: block;\n}\n.cg-tooltip-list-cell {\n  display: inline-flex;\n}\n.cg-tooltip-list-symbol {\n  display: block;\n  margin-right: 3px;\n  width: 6px;\n  height: 6px;\n  vertical-align: middle;\n  border-radius: 50%;\n  border: 1px solid rgba(0,0,0,.4);\n}\n.cg-tooltip-symbol-legacy {\n  border-radius: 4px;\n  margin-right: 5px;\n  height: 8px;\n  width: 8px;\n  display: inline-block;\n}\n.cg-tooltip-title-legacy {\n  font-weight: 900;\n}\n\n/* Tooltip symbol circle */\n.cg-tooltip-symbol.circle {\n  height: 10px;\n  width: 10px;\n  display: inline-block;\n  border-radius: 50%;\n  border: 1px solid rgba(0,0,0,.4);\n}\n/* Tooltip symbol line */\n.cg-tooltip-symbol.line {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    transform: scale(1.2, 0.2);\n}\n/* Tooltip symbol diamond */\n.cg-tooltip-symbol.diamond {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    transform: rotate(45deg);\n    border-radius: 0px;\n}\n/* Tooltip symbol square */\n.cg-tooltip-symbol.square {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    border-radius: 0px;\n    border: 1px solid rgba(0,0,0,.4);\n}\n\n","lang":"css"},"children":[]}]}]},{"$$mdtype":"Tag","name":"iframe","attributes":{"src":"https://dc2-documentation.s3.amazonaws.com/documentation/slb-docs-test/5.0/examples/vue/tutorials/index.html#/WellLog/MultiWell/LazyLoading/lazyLoading?section=result&extract=true","width":"100%","height":"673.5px","style":{"border":"none"}},"children":[]}]},"headings":[{"value":"Lazy Loading","id":"lazy-loading","depth":1},{"value":"Create Proxy Track","id":"create-proxy-track","depth":3},{"value":"Result","id":"result","depth":3}],"frontmatter":{"title":"Lazy Loading","seo":{"title":"Lazy Loading"}},"lastModified":"2026-02-11T19:54:32.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/solutions/geotoolkit/tutorials/well-log/multi-well/lazy-loading","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}