Giter Club home page Giter Club logo

Comments (11)

trusktr avatar trusktr commented on August 24, 2024 12

For reference, here are two fully-working versions that aren't webpack-specific (pardon the @type comment syntax for TypeScript types):

without a worker
    <canvas id="harpCanvas"></canvas>
    <style>
        #harpCanvas {
            width: 500px;
            height: 300px;
            padding: 0;
            border: 0;
        }
    </style>
import { MapView } from "@here/harp-mapview";
import { GeoCoordinates } from "@here/harp-geoutils";
import {
    APIFormat,
    AuthenticationMethod,
    OmvDataSource
} from "@here/harp-omv-datasource";
import { OmvTileDecoder } from "@here/harp-omv-datasource/index-worker";
import { MapControls } from "@here/harp-map-controls";

const canvas = /** @type {HTMLCanvasElement} */ (document.getElementById(
    "harpCanvas"
));

const mapView = new MapView({
    canvas,

    theme:
        "https://unpkg.com/@here/[email protected]/resources/berlin_tilezen_base.json",

    /**
     * This is the part I was confused with: ignore these options, instead
     * set the 'decoder' option in the 'OmvDataSource', see below.
     */
    // decoderUrl: "harp-gl-decoders.bundle.js",
    // decoderCount: 0,

    maxVisibleDataSourceTiles: 40,
    tileCacheSize: 100
});

mapView.camera.position.set(0, 0, 800);
mapView.geoCenter = new GeoCoordinates(40.70398928, -74.01319808, 0);
mapView.resize(canvas.clientWidth, canvas.clientHeight);

const dataSource = new OmvDataSource({
    apiFormat: APIFormat.XYZOMV,
    styleSetName: "tilezen",

    baseUrl: "https://vector.hereapi.com/v2/vectortiles/base/mc",
    authenticationCode: "YOUR_API_KEY_HERE",
    authenticationMethod: {
        method: AuthenticationMethod.QueryString,
        name: "apikey"
    },

    // This here! Set this to disable workers and make it load in the same thread (I
    // haven't noticed any performance issue on my slow intel i5 laptop).
    decoder: new OmvTileDecoder()
});

mapView.addDataSource(dataSource);

MapControls.create(mapView);
with a worker
    <canvas id="harpCanvas"></canvas>
    <style>
        #harpCanvas {
            width: 500px;
            height: 300px;
            padding: 0;
            border: 0;
        }
    </style>
import { MapView } from "@here/harp-mapview";
import { GeoCoordinates } from "@here/harp-geoutils";
import {
    APIFormat,
    AuthenticationMethod,
    OmvDataSource
} from "@here/harp-omv-datasource";
import { MapControls, MapControlsUI } from "@here/harp-map-controls";

// import OmvTileDecoderService inside a web Worker with vanilla JS, thanks to
// the JSPM ES Module CDN (https://jspm.io).
const workerCode = `
    async function main() {
        const { OmvTileDecoderService } = (
            await import('https://dev.jspm.io/@here/harp-omv-datasource/index-worker')
        ).default

        OmvTileDecoderService.start()
    }

    main()
`;
const blob = new Blob([workerCode], { type: "application/javascript" });

const canvas = /** @type {HTMLCanvasElement} */ (document.getElementById(
    "harpCanvas"
));

const map = new MapView({
    canvas,

    theme:
        "https://unpkg.com/@here/[email protected]/resources/berlin_tilezen_base.json",

    decoderUrl: URL.createObjectURL(blob),

    // For tile cache optimization:
    maxVisibleDataSourceTiles: 40,
    tileCacheSize: 100
});

map.setCameraGeolocationAndZoom(
    new GeoCoordinates(1.278676, 103.850216),
    16
);

const mapControls = new MapControls(map);
const ui = new MapControlsUI(mapControls);
canvas.parentElement.appendChild(ui.domElement);

map.resize(canvas.clientWidth, canvas.clientHeight);

const omvDataSource = new OmvDataSource({
    baseUrl: "https://vector.hereapi.com/v2/vectortiles/base/mc",
    authenticationCode: "YOUR_API_KEY_HERE",
    authenticationMethod: {
        method: AuthenticationMethod.QueryString,
        name: "apikey"
    },

    apiFormat: APIFormat.XYZOMV,
    styleSetName: "tilezen"
});

map.addDataSource(omvDataSource);

from harp.gl.

trusktr avatar trusktr commented on August 24, 2024 1

Ah, I see. It wasn't obvious from the docs that we could pass an instance to decoder, decoder: new OmvTileDecoder().

Anywho, I got the worker working (above) with native ES Module imports inside the worker using import('https://dev.jspm.io/@here/harp-omv-datasource/index-worker'), so I no longer need to try the non-worker version (though good to know!).

EDIT: Aah, I got confused with decoder* options of MapView, which is what I was fiddling, and I didn't realize I needed to set an option for the OmvDataSource).

from harp.gl.

trusktr avatar trusktr commented on August 24, 2024

As an example, take into consideration web applications that use native ES Modules, with no build steps.

ES Modules inside Web Workers are out now. πŸŽ‰ https://www.chromestatus.com/feature/5761300827209728

from harp.gl.

trusktr avatar trusktr commented on August 24, 2024

As a related question, how do we run without a worker? I tried

    const canvas = document.getElementById("harpCanvas");
    const mapView = new MapView({
        canvas,
        theme:
            "https://unpkg.com/@here/[email protected]/resources/berlin_tilezen_base.json"

        // decoderUrl: "harp-gl-decoders.bundle.js"
    });

    mapView.camera.position.set(0, 0, 800);
    mapView.geoCenter = new GeoCoordinates(40.70398928, -74.01319808, 0);
    mapView.resize(canvas.clientWidth, canvas.clientHeight);

    const dataSource = new OmvDataSource({
        baseUrl: "https://vector.hereapi.com/v2/vectortiles/base/mc",
        apiFormat: APIFormat.XYZOMV,
        styleSetName: "tilezen",
        authenticationCode: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        authenticationMethod: {
            method: AuthenticationMethod.QueryString,
            name: "apikey"
        }
    });

    mapView.addDataSource(dataSource);

    MapControls.create(mapView);

but I get the error

MapView: Failed to connect to datasource anonymous-datasource#1: Error during worker initialization: Uncaught SyntaxError: Unexpected token '<' in http://localhost:3000/decoder.bundle.js:1

Because my server sends back a 404 page (HTML page starts with <).

EDIT: Setting MapView's decoderCount to 0 got me further, this time saying TileLoader: [anonymous-datasource#1]: failed to load tile 327439125 Error: ConcurrentWorkerSet#postMessage: no workers started.

from harp.gl.

trusktr avatar trusktr commented on August 24, 2024

I tried the same exact demo as listed on the website's tutorial, but I get the same error. This is the tutorial code:

    import { MapView } from "@here/harp-mapview";
    import { GeoCoordinates } from "@here/harp-geoutils";
    import {
        APIFormat,
        OmvDataSource
    } from "@here/harp-omv-datasource";
    import { MapControls, MapControlsUI } from "@here/harp-map-controls";
    import { OmvTileDecoderService } from "@here/harp-omv-datasource/index-worker";

    const canvas = document.getElementById("harpCanvas");
    const map = new MapView({
        canvas,

        theme:
            "https://unpkg.com/@here/[email protected]/resources/berlin_tilezen_base.json",

        //For tile cache optimization:
        maxVisibleDataSourceTiles: 40,
        tileCacheSize: 100
    });

    map.setCameraGeolocationAndZoom(
        new GeoCoordinates(1.278676, 103.850216),
        16
    );

    const mapControls = new MapControls(map);
    const ui = new MapControlsUI(mapControls);
    canvas.parentElement.appendChild(ui.domElement);

    mapControls.maxPitchAngle = 90;
    // mapControls.setRotation(6.3, 50);
    // mapControls.camera.rotation

    map.resize(window.innerWidth, window.innerHeight);
    window.onresize = () => map.resize(window.innerWidth, window.innerHeight);

    const omvDataSource = new OmvDataSource({
        baseUrl: "https://xyz.api.here.com/tiles/herebase.02",
        apiFormat: APIFormat.XYZOMV,
        styleSetName: "tilezen",
        authenticationCode: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    });

    map.addDataSource(omvDataSource);

Also I get an error that mapControls.setRotation doesn't exist, it is an undefined property.

from harp.gl.

trusktr avatar trusktr commented on August 24, 2024

I think what could be a nice solution would be to publish the output code in ESM format. Then people could import that file directly in the worker by importing it from unpkg or from locally-served node_modules, for example, without build steps.

EDIT: Plus! If everything is published as ES Modules, this also improves Webpack tree shaking for people who go that route.

from harp.gl.

trusktr avatar trusktr commented on August 24, 2024

Well how about that! Google Chrome's native ES Modules can load OmvTileDecoderService in a web worker directly from JSPM's ES Module CDN (which ports mostly anything found on NPM to ES Modules).

Try running this in your browser console and wait for the worker to log the OmvTileDecoderService class to console:

// import OmvTileDecoderService inside a web Worker with vanilla JS, thanks to
// the JSPM ES Module CDN (https://jspm.io).
{
    const workerCode = `
        import HarpOmvDatasource from 'https://dev.jspm.io/@here/harp-omv-datasource/index-worker'
        console.log(HarpOmvDatasource.OmvTileDecoderService)
    `;

    const blob = new Blob([workerCode], {type: 'application/javascript'});
    const worker = new Worker(URL.createObjectURL(blob), {type: 'module'});
}

Now, I need to figure how to make the main thread Harp code not try to load decoder.bundle.js and use the custom-made worker.

Note, I do see the main thread sends this message:

{
  service: "worker-service-manager",
  type: "initialized"
}

Any tips?

from harp.gl.

trusktr avatar trusktr commented on August 24, 2024

Ah! The key is decoderUrl, which can take the blob URL. So this gets me further:

    const workerCode = `
        import HarpOmvDatasource from 'https://dev.jspm.io/@here/harp-omv-datasource/index-worker'
        const { OmvTileDecoderService } = HarpOmvDatasource
        console.log('IN WORKER!!', OmvTileDecoderService)
        OmvTileDecoderService.start()
    `;
    const blob = new Blob([workerCode], { type: "application/javascript" });

    const canvas = document.getElementById("harpCanvas");
    const map = new MapView({
        canvas,
        theme: "https://unpkg.com/@here/[email protected]/resources/berlin_tilezen_base.json",
        decoderUrl: URL.createObjectURL(blob),
    });

But now the problem is,

MapView: Failed to connect to datasource anonymous-datasource#1: Error during worker initialization: Uncaught SyntaxError: Cannot use import statement outside a module in blob:http://localhost:3000/41ff4879-b970-441b-a190-15172a2a87cd:2

Because internally MapView is not making the web worker with {type: 'module'}. That would be an easy fix to the harp.gl source...

from harp.gl.

trusktr avatar trusktr commented on August 24, 2024

Okay! I got past that error by using the import() function instead of the import syntax, thus not requiring MapView to instantiate the web worker with {type: 'module'}. Like this:

    const workerCode = `
        async function main() {
            const { OmvTileDecoderService } = (
                await import('https://dev.jspm.io/@here/harp-omv-datasource/index-worker')
            ).default

            OmvTileDecoderService.start()
        }

        main()
    `;
    const blob = new Blob([workerCode], { type: "application/javascript" });

    const canvas = document.getElementById("harpCanvas");
    const map = new MapView({
        canvas,
        theme: "https://unpkg.com/@here/[email protected]/resources/berlin_tilezen_base.json",
        decoderUrl: URL.createObjectURL(blob),
    });

However now I'm getting HTTP 401 errors from the Here API (https://xyz.api.here.com/tiles/herebase.02/14), although I did enter my API key, but that's a totally different problem than in this issue.

So, for anyone not running with Webpack, the above should get them running, assuming other stuff like API access works.

from harp.gl.

nzjony avatar nzjony commented on August 24, 2024

@trusktr , thanks for your indepth research! I'm not an expert on webpack, so I have asked in our internal chat to find someone who can perhaps give you a more informed opinion.

Just one comment, you asked above:

As a related question, how do we run without a worker?

Here is a DataSource that runs in the main thread, it isn't a long term solution, but for debugging etc, it can be helpful to get something up and running quickly, note the decoder parameter.

 const omvDataSource = new OmvDataSource({
        baseUrl: "https://vector.hereapi.com/v2/vectortiles/base/mc",
        apiFormat: APIFormat.XYZOMV,
        styleSetName: "tilezen",
        maxZoomLevel: 17,
        authenticationCode: apikey,
        authenticationMethod: {
            method: AuthenticationMethod.QueryString,
            name: "apikey"
        },
        copyrightInfo,
        decoder: new OmvTileDecoder()
    });

from harp.gl.

stale avatar stale commented on August 24, 2024

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

from harp.gl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.