Pocket — parches de estilo (Mapbox)
Aplicar parches rápidos a estilos Mapbox: actualizar source
/data
y redefinir fill-color
con interpolate
(stops ordenados).
Fuente: cluster_0191 — Integración de color/escala en JSON de estilos.
Contrato mínimo
Entrada: style
(dict leído desde .json
), layer_id
objetivo, stops [(x1,"#hex1"), ...]
.
Salida: style
modificado (se recomienda escribir a un nuevo archivo).
Garantías: no mutar en sitio (deep copy) y ordenar stops por valor ascendente.
1) Utilidades básicas (layers & sources)
import copy
def find_layer(style, layer_id):
for ly in style.get("layers", []):
if ly.get("id") == layer_id:
return ly
raise KeyError(f"Layer '{layer_id}' no encontrado")
def update_source_url(style, source_id, new_value):
s = style.get("sources", {}).get(source_id)
if not s:
raise KeyError(f"Source '{source_id}' no encontrado")
# vector tiles → url; geojson → data
if s.get("type") == "vector":
s["url"] = new_value
elif s.get("type") == "geojson":
s["data"] = new_value
else:
# si es raster/otros, cubrir casos según tu catálogo
s["url"] = new_value
2) fill-color
con interpolate
(lineal)
Expresión canónica:
["interpolate", ["linear"], ["get", "<prop>"], x1, "#hex1", x2, "#hex2", ...]
Helper seguro:
def set_fill_color_linear(style, layer_id, prop, stops):
st = copy.deepcopy(style)
ly = find_layer(st, layer_id)
ly.setdefault("paint", {})
# stops ordenados y únicos
stops_sorted = sorted({float(x): str(c) for x, c in stops}.items())
expr = ["interpolate", ["linear"], ["get", prop]]
for x, c in stops_sorted:
expr += [x, c]
ly["paint"]["fill-color"] = expr
return st
Uso:
# p. ej., para 'valor' entre 0 y 100
st2 = set_fill_color_linear(style, "departamentos-fill", "valor",
[(0, "#f7fbff"), (25, "#c6dbef"), (50, "#6baed6"), (75, "#2171b5"), (100, "#08306b")])
3) Parches combinados: source + color
def patch_style(style, layer_id, prop, stops, source_id=None, new_source=None):
st = copy.deepcopy(style)
if source_id and new_source:
update_source_url(st, source_id, new_source)
return set_fill_color_linear(st, layer_id, prop, stops)
4) QA rápido
- Existencia:
layer_id
ysource_id
válidos. - Monotonía: stops ordenados ascendente; valores únicos.
- Tipo de layer:
fill-color
solo para layersfill
. - Propiedad:
["get", prop]
debe existir en el source (o el color caería al primer/último stop). - Salida: persistir con
ensure_ascii=False
y backup del.json
original.
import json, pathlib
path_out = pathlib.Path("style_patched.json")
with path_out.open("w", encoding="utf-8") as f:
json.dump(st2, f, ensure_ascii=False, indent=2)
5) Trampas comunes (y fixes)
KeyError
en búsquedas anidadas → usar helpers ysetdefault
.- Reemplazo parcial de la expresión → preferible rearmar toda la lista
interpolate
. - Escala inconsistente con los datos → calcular rangos (min/percentiles) antes de definir stops.
- Hex inválidos o mezclas RGBA/hex → normalizar a
#RRGGBB
antes de inyectar.
Ver también
metodos/charts_and_styles.md
(política de escalas,linspace
, reemplazo seguro).pocket/categorical_colormaps.md
(paletas discretas consistentes en el lado Python).