1
- import { FEATURE_TYPES } from 'Core/Feature' ;
2
1
import Cache from 'Core/Scheduler/Cache' ;
3
2
import Fetcher from 'Provider/Fetcher' ;
4
- import * as mapbox from '@mapbox/mapbox-gl-style-spec' ;
5
3
import { Color } from 'three' ;
6
4
import { deltaE } from 'Renderer/Color' ;
7
5
import Coordinates from 'Core/Geographic/Coordinates' ;
@@ -13,8 +11,6 @@ const cacheStyle = new Cache();
13
11
const matrix = document . createElementNS ( 'http://www.w3.org/2000/svg' , 'svg' ) . createSVGMatrix ( ) ;
14
12
const canvas = document . createElement ( 'canvas' ) ;
15
13
16
- const inv255 = 1 / 255 ;
17
-
18
14
function baseAltitudeDefault ( properties , ctx ) {
19
15
return ctx ?. coordinates ?. z || 0 ;
20
16
}
@@ -47,37 +43,6 @@ export function readExpression(property, ctx) {
47
43
return property ;
48
44
}
49
45
50
- function rgba2rgb ( orig ) {
51
- if ( ! orig ) {
52
- return { } ;
53
- } else if ( orig . stops || orig . expression ) {
54
- return { color : orig } ;
55
- } else if ( typeof orig == 'string' ) {
56
- const result = orig . match ( / (?: ( ( h s l | r g b ) a ? * \( ( [ \d . % ] + (?: d e g | g ? r a d | t u r n ) ? ) [ , ] * ( [ \d . % ] + ) [ , ] * ( [ \d . % ] + ) [ , / ] * ( [ \d . % ] * ) \) ) | ( # ( (?: [ \d \w ] { 3 } ) { 1 , 2 } ) ( [ \d \w ] { 1 , 2 } ) ? ) ) / i) ;
57
- if ( result === null ) {
58
- return { color : orig , opacity : 1.0 } ;
59
- } else if ( result [ 7 ] ) {
60
- let opacity = 1.0 ;
61
- if ( result [ 9 ] ) {
62
- opacity = parseInt ( result [ 9 ] . length == 1 ? `${ result [ 9 ] } ${ result [ 9 ] } ` : result [ 9 ] , 16 ) * inv255 ;
63
- }
64
- return { color : `#${ result [ 8 ] } ` , opacity } ;
65
- } else if ( result [ 1 ] ) {
66
- return { color : `${ result [ 2 ] } (${ result [ 3 ] } ,${ result [ 4 ] } ,${ result [ 5 ] } )` , opacity : ( result [ 6 ] ? Number ( result [ 6 ] ) : 1.0 ) } ;
67
- }
68
- }
69
- }
70
-
71
- function readVectorProperty ( property , options ) {
72
- if ( property != undefined ) {
73
- if ( mapbox . expression . isExpression ( property ) ) {
74
- return mapbox . expression . createExpression ( property , options ) . value ;
75
- } else {
76
- return property ;
77
- }
78
- }
79
- }
80
-
81
46
async function loadImage ( source ) {
82
47
let promise = cacheStyle . get ( source , 'null' ) ;
83
48
if ( ! promise ) {
@@ -700,217 +665,6 @@ class Style {
700
665
this . context = ctx ;
701
666
}
702
667
703
- /**
704
- * set Style from (geojson-like) properties.
705
- * @param {Object } properties (geojson-like) properties.
706
- * @param {FeatureContext } featCtx the context of the feature
707
- *
708
- * @returns {StyleOptions } containing all properties for itowns.Style
709
- */
710
- static setFromProperties ( properties , featCtx ) {
711
- const type = featCtx . type ;
712
- const style = { } ;
713
- if ( type === FEATURE_TYPES . POINT ) {
714
- const point = {
715
- ...( properties . fill !== undefined && { color : properties . fill } ) ,
716
- ...( properties [ 'fill-opacity' ] !== undefined && { opacity : properties [ 'fill-opacity' ] } ) ,
717
- ...( properties . stroke !== undefined && { line : properties . stroke } ) ,
718
- ...( properties . radius !== undefined && { radius : properties . radius } ) ,
719
- } ;
720
- if ( Object . keys ( point ) . length ) {
721
- style . point = point ;
722
- }
723
- const text = {
724
- ...( properties [ 'label-color' ] !== undefined && { color : properties [ 'label-color' ] } ) ,
725
- ...( properties [ 'label-opacity' ] !== undefined && { opacity : properties [ 'label-opacity' ] } ) ,
726
- ...( properties [ 'label-size' ] !== undefined && { size : properties [ 'label-size' ] } ) ,
727
- } ;
728
- if ( Object . keys ( point ) . length ) {
729
- style . text = text ;
730
- }
731
- const icon = {
732
- ...( properties . icon !== undefined && { source : properties . icon } ) ,
733
- ...( properties [ 'icon-scale' ] !== undefined && { size : properties [ 'icon-scale' ] } ) ,
734
- ...( properties [ 'icon-opacity' ] !== undefined && { opacity : properties [ 'icon-opacity' ] } ) ,
735
- ...( properties [ 'icon-color' ] !== undefined && { color : properties [ 'icon-color' ] } ) ,
736
- } ;
737
- if ( Object . keys ( icon ) . length ) {
738
- style . icon = icon ;
739
- }
740
- } else {
741
- const stroke = {
742
- ...( properties . stroke !== undefined && { color : properties . stroke } ) ,
743
- ...( properties [ 'stroke-width' ] !== undefined && { width : properties [ 'stroke-width' ] } ) ,
744
- ...( properties [ 'stroke-opacity' ] !== undefined && { opacity : properties [ 'stroke-opacity' ] } ) ,
745
- } ;
746
- if ( Object . keys ( stroke ) . length ) {
747
- style . stroke = stroke ;
748
- }
749
- if ( type !== FEATURE_TYPES . LINE ) {
750
- const fill = {
751
- ...( properties . fill !== undefined && { color : properties . fill } ) ,
752
- ...( properties [ 'fill-opacity' ] !== undefined && { opacity : properties [ 'fill-opacity' ] } ) ,
753
- } ;
754
- if ( Object . keys ( fill ) . length ) {
755
- style . fill = fill ;
756
- }
757
- }
758
- }
759
- return style ;
760
- }
761
-
762
- /**
763
- * set Style from vector tile layer properties.
764
- * @param {Object } layer vector tile layer.
765
- * @param {Object } sprites vector tile layer.
766
- * @param {Number } [order=0]
767
- * @param {Boolean } [symbolToCircle=false]
768
- *
769
- * @returns {StyleOptions } containing all properties for itowns.Style
770
- */
771
- static setFromVectorTileLayer ( layer , sprites , order = 0 , symbolToCircle = false ) {
772
- const style = {
773
- fill : { } ,
774
- stroke : { } ,
775
- point : { } ,
776
- text : { } ,
777
- icon : { } ,
778
- } ;
779
-
780
- layer . layout = layer . layout || { } ;
781
- layer . paint = layer . paint || { } ;
782
-
783
- style . order = order ;
784
-
785
- if ( layer . type === 'fill' ) {
786
- const { color, opacity } = rgba2rgb ( readVectorProperty ( layer . paint [ 'fill-color' ] || layer . paint [ 'fill-pattern' ] , { type : 'color' } ) ) ;
787
- style . fill . color = color ;
788
- style . fill . opacity = readVectorProperty ( layer . paint [ 'fill-opacity' ] ) || opacity ;
789
- if ( layer . paint [ 'fill-pattern' ] ) {
790
- try {
791
- style . fill . pattern = {
792
- id : layer . paint [ 'fill-pattern' ] ,
793
- source : sprites . source ,
794
- cropValues : sprites [ layer . paint [ 'fill-pattern' ] ] ,
795
- } ;
796
- } catch ( err ) {
797
- err . message = `VTlayer '${ layer . id } ': argument sprites must not be null when using layer.paint['fill-pattern']` ;
798
- throw err ;
799
- }
800
- }
801
-
802
- if ( layer . paint [ 'fill-outline-color' ] ) {
803
- const { color, opacity } = rgba2rgb ( readVectorProperty ( layer . paint [ 'fill-outline-color' ] , { type : 'color' } ) ) ;
804
- style . stroke . color = color ;
805
- style . stroke . opacity = opacity ;
806
- style . stroke . width = 1.0 ;
807
- style . stroke . dasharray = [ ] ;
808
- }
809
- } else if ( layer . type === 'line' ) {
810
- const prepare = readVectorProperty ( layer . paint [ 'line-color' ] , { type : 'color' } ) ;
811
- const { color, opacity } = rgba2rgb ( prepare ) ;
812
- style . stroke . dasharray = readVectorProperty ( layer . paint [ 'line-dasharray' ] ) ;
813
- style . stroke . color = color ;
814
- style . stroke . lineCap = layer . layout [ 'line-cap' ] ;
815
- style . stroke . width = readVectorProperty ( layer . paint [ 'line-width' ] ) ;
816
- style . stroke . opacity = readVectorProperty ( layer . paint [ 'line-opacity' ] ) || opacity ;
817
- } else if ( layer . type === 'circle' || symbolToCircle ) {
818
- const { color, opacity } = rgba2rgb ( readVectorProperty ( layer . paint [ 'circle-color' ] , { type : 'color' } ) ) ;
819
- style . point . color = color ;
820
- style . point . opacity = opacity ;
821
- style . point . radius = readVectorProperty ( layer . paint [ 'circle-radius' ] ) ;
822
- } else if ( layer . type === 'symbol' ) {
823
- // overlapping order
824
- style . text . zOrder = readVectorProperty ( layer . layout [ 'symbol-z-order' ] ) ;
825
- if ( style . text . zOrder == 'auto' ) {
826
- style . text . zOrder = readVectorProperty ( layer . layout [ 'symbol-sort-key' ] ) || 'Y' ;
827
- } else if ( style . text . zOrder == 'viewport-y' ) {
828
- style . text . zOrder = 'Y' ;
829
- } else if ( style . text . zOrder == 'source' ) {
830
- style . text . zOrder = 0 ;
831
- }
832
-
833
- // position
834
- style . text . anchor = readVectorProperty ( layer . layout [ 'text-anchor' ] ) ;
835
- style . text . offset = readVectorProperty ( layer . layout [ 'text-offset' ] ) ;
836
- style . text . padding = readVectorProperty ( layer . layout [ 'text-padding' ] ) ;
837
- style . text . size = readVectorProperty ( layer . layout [ 'text-size' ] ) ;
838
- style . text . placement = readVectorProperty ( layer . layout [ 'symbol-placement' ] ) ;
839
- style . text . rotation = readVectorProperty ( layer . layout [ 'text-rotation-alignment' ] ) ;
840
-
841
- // content
842
- style . text . field = readVectorProperty ( layer . layout [ 'text-field' ] ) ;
843
- style . text . wrap = readVectorProperty ( layer . layout [ 'text-max-width' ] ) ;
844
- style . text . spacing = readVectorProperty ( layer . layout [ 'text-letter-spacing' ] ) ;
845
- style . text . transform = readVectorProperty ( layer . layout [ 'text-transform' ] ) ;
846
- style . text . justify = readVectorProperty ( layer . layout [ 'text-justify' ] ) ;
847
-
848
- // appearance
849
- const { color, opacity } = rgba2rgb ( readVectorProperty ( layer . paint [ 'text-color' ] , { type : 'color' } ) ) ;
850
- style . text . color = color ;
851
- style . text . opacity = readVectorProperty ( layer . paint [ 'text-opacity' ] ) || ( opacity !== undefined && opacity ) ;
852
-
853
- style . text . font = readVectorProperty ( layer . layout [ 'text-font' ] ) ;
854
- const haloColor = readVectorProperty ( layer . paint [ 'text-halo-color' ] , { type : 'color' } ) ;
855
- if ( haloColor ) {
856
- style . text . haloColor = haloColor . color || haloColor ;
857
- style . text . haloWidth = readVectorProperty ( layer . paint [ 'text-halo-width' ] ) ;
858
- style . text . haloBlur = readVectorProperty ( layer . paint [ 'text-halo-blur' ] ) ;
859
- }
860
-
861
- // additional icon
862
- const iconImg = readVectorProperty ( layer . layout [ 'icon-image' ] ) ;
863
- if ( iconImg ) {
864
- try {
865
- style . icon . id = iconImg ;
866
- if ( iconImg . stops ) {
867
- const iconCropValue = {
868
- ...( iconImg . base !== undefined && { base : iconImg . base } ) ,
869
- stops : iconImg . stops . map ( ( stop ) => {
870
- let cropValues = sprites [ stop [ 1 ] ] ;
871
- if ( stop [ 1 ] . includes ( '{' ) ) {
872
- cropValues = function _ ( p ) {
873
- const id = stop [ 1 ] . replace ( / \{ ( .+ ?) \} / g, ( a , b ) => ( p [ b ] || '' ) ) . trim ( ) ;
874
- cropValues = sprites [ id ] ;
875
- return sprites [ id ] ;
876
- } ;
877
- }
878
- return [ stop [ 0 ] , cropValues ] ;
879
- } ) ,
880
- } ;
881
- style . icon . cropValues = iconCropValue ;
882
- } else {
883
- style . icon . cropValues = sprites [ iconImg ] ;
884
- if ( iconImg [ 0 ] . includes ( '{' ) ) {
885
- style . icon . cropValues = function _ ( p ) {
886
- const id = iconImg . replace ( / \{ ( .+ ?) \} / g, ( a , b ) => ( p [ b ] || '' ) ) . trim ( ) ;
887
- style . icon . cropValues = sprites [ id ] ;
888
- return sprites [ id ] ;
889
- } ;
890
- }
891
- }
892
- style . icon . source = sprites . source ;
893
- style . icon . size = readVectorProperty ( layer . layout [ 'icon-size' ] ) || 1 ;
894
- const { color, opacity } = rgba2rgb ( readVectorProperty ( layer . paint [ 'icon-color' ] , { type : 'color' } ) ) ;
895
- style . icon . color = color ;
896
- style . icon . opacity = readVectorProperty ( layer . paint [ 'icon-opacity' ] ) || ( opacity !== undefined && opacity ) ;
897
- } catch ( err ) {
898
- err . message = `VTlayer '${ layer . id } ': argument sprites must not be null when using layer.layout['icon-image']` ;
899
- throw err ;
900
- }
901
- }
902
- }
903
- // VectorTileSet: by default minZoom = 0 and maxZoom = 24
904
- // https://docs.mapbox.com/style-spec/reference/layers/#maxzoom and #minzoom
905
- // Should be move to layer properties, when (if) one mapBox layer will be considered as several itowns layers.
906
- // issue https://github.com/iTowns/itowns/issues/2153 (last point)
907
- style . zoom = {
908
- min : layer . minzoom || 0 ,
909
- max : layer . maxzoom || 24 ,
910
- } ;
911
- return style ;
912
- }
913
-
914
668
/**
915
669
* Applies the style.fill to a polygon of the texture canvas.
916
670
* @param {CanvasRenderingContext2D } txtrCtx The Context 2D of the texture canvas.
0 commit comments