Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error using text-field with multi-part format expression in style: text.split is not a function #1233

Open
mzmcgrat opened this issue Dec 20, 2024 · 3 comments

Comments

@mzmcgrat
Copy link
Contributor

I'm using protomaps-themes-base in my project to feed one of its mapbox styles into the stylefunction from this project to style a VectorTile layer, and it's throwing this error, (truncated here) at certain zoom levels/locations where the affected layer styles become used:

Uncaught TypeError: text.split is not a function
    measureAndCacheTextWidth canvas.js:359
    execute_ Executor.js:1023
    execute Executor.js:1259
    execute ExecutorGroup.js:396
    renderDeclutter VectorTileLayer.js:604
    renderDeclutter BaseVector.js:245
    declutter Composite.js:176

The same style appears to work with the same data source when used with maplibre: https://maps.protomaps.com/#map=14.15/40.62785/-73.9942&theme=light&lang=en&tiles=https://demo-bucket.protomaps.com/v4.pmtiles.

It appears that if you use a text-field with a single-part format expression (don't know the proper mapbox style terminology) it works, but if you use a multi-part format expression like in the example shown in https://docs.mapbox.com/mapbox-gl-js/example/display-and-style-rich-text-labels/, the text value passed to measureAndCacheTextWidth can end up as an array like ["",​'normal 400 12px/1.2 "Noto Sans"',​"\n",​"",​"",​'normal 400 12px/1.2 "Noto Sans"',"\n","","",'normal 400 12px/1.2 "Noto Sans"'], which obviously has no split method. The documentation for format expression implies that multiple text inputs with overrides are valid: https://docs.mapbox.com/style-spec/reference/expressions/#types-format , so I'm not sure what I'm doing wrong here. I don't believe it's a case of referencing a missing field in the feature, since it still gives the same error even if I change the ['get', 'name:en'] expressions to strings.

@ahocevar
Copy link
Member

ahocevar commented Dec 20, 2024

Can you share the style you are using? Rich text handling per se works great in ol-mapbox-style, so maybe there is something else wrong? I've seen the same error when people try to render text that is a number rather than a string.

@mzmcgrat
Copy link
Contributor Author

The actual style I'm using from protomaps-themes-base has about 70 layers, so it would be too complex to post, but I was able to come up with a minimal example that encounters the error. It uses static text instead of getting text values from the features, yet it still encounters the error. Of course, I'm normally using my own copy of the pmtiles file, but this example works outside my network.

import 'ol/ol.css'  //My project probably has a preprocessor to allow this
import Map from 'ol/Map'
import View from 'ol/View'
import VectorTileLayer from 'ol/layer/VectorTile'
import { PMTilesVectorSource } from 'ol-pmtiles'
import { stylefunction } from 'ol-mapbox-style'

let source= new PMTilesVectorSource({
	url: "https://build.protomaps.com/20241209.pmtiles",
})

let layer= new VectorTileLayer({
	declutter: true,
	source: source,
	style: null,
})

let style = {
	version: 8,
	layers: [
		{
			"id": "roads_labels_major",
			"type": "symbol",
			"source": "protomaps",
			"source-layer": "roads",
			"minzoom": 11,
			"filter": [
				"in",
				"kind",
				"highway",
				"major_road"
			],
			"layout": {
				"symbol-placement": "line",
				"text-font": [
					"Noto Sans Regular"
				],
				"text-field": [
					"format",
					"text1",
					{},
					//Removing the next two array elements prevents the error
					"text2",
					{},
				],
				"text-size": 12
			},
			"paint": {
				"text-color": "#938a8d",
				"text-halo-color": "#ffffff",
				"text-halo-width": 1,
				"text-halo-blur": 1
			}
		}
	],
	sources: {
		protomaps: {
			type: "vector",
		},
	},
}

stylefunction(layer, style, 'protomaps')

let view= new View({
	zoom: 15,
	center: [-8235240.97715229, 4960357.931332409],
})

let map= new Map({
	target: "map",
	projection: "EPSG:3857",
	layers: [
		layer,
	],
	view: view,
})

@ahocevar
Copy link
Member

Thanks for the reproduction case, @mzmcgrat. The problem here is that OpenLayers does not support rich text with placement: 'line'. I created openlayers/openlayers#16497.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants