Google 地图 API - 如何获取渐变中使用的最大强度值?
GoogleMaps API - How to get the maxIntensity value used in the gradient?
我想达到的目标
我正在尝试为我的热图的梯度建立图例 - 我使用 GoogleMaps API 成功创建 - 我唯一缺少的是梯度(即在热图上显示最高强度的值)。
我在这个主题上找到了一个很好的主题,它总结并完美地说明了我想要实现的目标,但遗憾的是我感兴趣的部分不起作用:HowTo create legend for google Heatmap?
我试过的
我尝试了几件事(几乎所有我能做的事),包括:
- 使用“heatmap.get('maxIntensity') 属性,但只有在用户事先设置了maxIntensity时才有效,这对我来说是不可能的,因为主要我在使用的数据中可能存在的差异
- 试图找到 maxIntensity 的数学表达式以自己重新计算它
- 深入研究 Google 的 API 以找出他们对我们隐藏的内容(即找到一个类似于上面 link 中给出的解决方案)
- 显然会转到 google 结果的第 10 页,并浏览 Whosebug 上似乎所有相关的主题
问题
所以现在我几乎没有解决方案:也许这里有人知道计算 maxIntensity 的神圣公式,或者比我更了解原始 API 来提取 maxIntensity 值?
什么我"found"
在使用控制台深入研究时,我 认为 我设法隔离了 Google 的 API 参与该过程的部分。它们有点重,但我不能做得更好。
这个显然有一个 属性 标识为 "maxIntensity":
google.maps.__gjsload__('visualization_impl', function (_) {
'use strict';
var i6 = function (a) {
for (var b = Array(a), c = 0; c < a; ++c) b[c] = 0;
for (var c = Array(a), d = 0; d < a; ++d) c[d] = b.concat();
return c
},
j6 = function (a) {
if (!a || !a.getLength()) return 1;
var b = new _.Xd;
a.forEach(function (a) {
a && b.extend(a.location || a)
});
var c = b.f.f,
d = b.b.b,
e = Math.max(b.f.b - c, b.b.f - d);
if (1E-9 > e) {
var f = 0;
a.forEach(function (a) {
a instanceof _.E ? ++f : f += a.weight
});
return Math.max(1, f)
}
var g = 800 / e,
h = i6(800),
l = 1;
a.forEach(function (a) {
if (a) {
var b = a.location || a;
a = a.weight || 1;
b = new _.I(Math.max(0, Math.min(799,
Math.floor((b.lat() - c) * g))), Math.max(0, Math.min(799, Math.floor((b.lng() - d) * g))));
h[b.x][b.y] += a;
l = Math.max(l, h[b.x][b.y])
}
});
return l
},
l6 = function (a, b) {
var c = [],
d = [],
e = 1E3 / (a.length - 1);
_.v(a, function (a, b) {
c.push(b * e);
d.push(_.gJ(a))
});
a = Array(1001);
for (var f = 0, g = 0; 1001 > g; ++g) g > c[f + 1] && ++f, a[g] = f < c.length - 1 ? k6(e * f, g, e * (f + 1), d[f], d[f + 1]) : d[d.length - 1], a[g].alpha *= b, a[g].alpha = _.Za(Math.floor(255 * a[g].alpha), 0, 255);
return a
},
k6 = function (a, b, c, d, e) {
if (a == c) return d;
a = (b - a) / (c - a);
return new _.dJ(Math.floor((e.j -
d.j) * a + d.j), Math.floor((e.f - d.f) * a + d.f), Math.floor((e.b - d.b) * a + d.b), (e.alpha - d.alpha) * a + d.alpha)
},
n6 = function (a, b, c) {
if (!m6) {
for (var d = Array(256), e = 0; 256 > e; ++e) {
for (var f = e, g = 0; 8 > g; ++g) f = f & 1 ? (3988292384 ^ f >>> 1) >>> 0 : f >>> 1;
d[e] = f
}
m6 = d
}
d = 4294967295;
e = b;
for (b += c; e < b; ++e) d = (m6[(d ^ a[e]) & 255] ^ d >>> 8) >>> 0;
return (d ^ 4294967295) >>> 0
},
p6 = function (a) {
this.f = a.createElement("div");
this.b = new o6(this)
},
o6 = _.oa("b"),
q6 = function (a, b) {
this.m = a;
this.b = 1;
this.f = [];
this.j = b
},
r6 = function (a, b, c) {
_.Rl(b.V, "");
var d = b.ownerDocument,
e, f, g, h;
if (_.Gz()) e = g = d.createElement("canvas"), _.$l(e), f = e.getContext("2d"), h = 1 < a.b;
else if (1 == _.W.type && _.Vk(_.W.version, 8)) e = new p6(d), f = e.b, g = e.getDiv(), h = !1;
else return;
e.width = e.height = 256;
b.V.appendChild(g);
e = a.get("projection");
g = a.get("radius");
g = Math.round(g / a.b) * a.b;
var l = 1 << b.zoom,
n = b.ac,
q = (256 + 2 * g) / a.b;
b = i6(q);
for (var r in n)
for (var u = n[r], x = e.fromLatLngToPoint(new _.E(u.K, u.L, !0)), A = e.fromLatLngToPoint(new _.E(u.O, u.P, !0)), x = new _.I(Math.min(x.x, A.x), Math.min(x.y, A.y)), x = new _.I(x.x +
g / l, x.y + g / l), u = a.m.search(u), A = 0, C = u.length; A < C; ++A) {
var D = u[A],
H = e.fromLatLngToPoint(new _.E(D.ea.x, D.ea.y)),
K = Math.floor((Math.floor((H.y - x.y) * l) + g) / a.b),
H = Math.floor((Math.floor((H.x - x.x) * l) + g) / a.b);
0 <= K && K < q && 0 <= H && H < q && (b[K][H] += D.weight)
}
r = a.f;
e = Math.floor(r.length / 2);
g = b.length;
l = g - e;
n = i6(g);
for (q = 0; q < g; ++q)
for (x = b[q], C = n[q], u = 0; u < g; ++u)
if (A = x[u])
for (D = u - e, K = Math.min(l, u + e + 1), H = Math.max(e, D); H < K; ++H) C[H] += A * r[H - D];
b = i6(g - 2 * e);
for (q = 0; q < g; ++q)
for (x = n[q], C = Math.max(e, q - e), D = Math.min(l, q + e + 1),
K = q - e, u = e, H = 0; u < l; ++u, ++H)
if (A = x[u])
for (var G = C; G < D; ++G) b[G - e][H] += A * r[G - K];
r = Math.ceil(256 / a.b);
r = f.createImageData(r, r);
e = a.get("gradient");
g = a.j;
l = e[e.length - 1];
c = e.length / c;
n = r.data;
x = q = 0;
for (u = b.length; x < u; ++x)
for (A = b[x], C = 0, D = A.length; C < D; ++C)(K = A[C]) || e[0].alpha ? (K = e[Math.floor(K * c)] || l, H = g ? K.alpha / 255 : 1, n[q++] = K.j * H, n[q++] = K.f * H, n[q++] = K.b * H, n[q++] = K.alpha) : q += 4;
h ? (d = d.createElement("canvas"), d.width = d.height = 256 / a.b, d.getContext("2d").putImageData(r, 0, 0), f.scale(a.b, a.b), f.drawImage(d, 0,
0)) : f.putImageData(r, 0, 0)
},
s6 = function (a, b) {
_.yf.call(this);
this.tileSize = new _.J(256, 256);
this.j = {};
var c = _.vf(-100, -300, 100, 300);
this.A = new _.dG(c, void 0);
c = _.vf(-90, -180, 90, 180);
this.f = _.jJ(c, function (a, b) {
return a.ea.b(b.ea) && a.weight == b.weight
});
this.S = [];
this.D = new _.zc;
this.b = 0;
this.m = new q6(this.f, a);
this.m.bindTo("projection", this, "projection", !0);
this.m.bindTo("gradient", this, "gradient", !0);
this.m.bindTo("radius", this, "radius", !0);
var d = this;
b(this.D, function (a) {
r6(d.m, a, d.b)
})
},
t6 = function (a,
b) {
var c = b.Z,
d = 1 << b.zoom,
e = a.get("radius"),
f = new _.I(256 * c.x / d, 256 * c.y / d),
c = _.vf((256 * c.x - e) / d, (256 * c.y - e) / d, (256 * (c.x + 1) + e) / d, (256 * (c.y + 1) + e) / d),
d = a.get("projection");
_.kJ(c, d, f, function (c) {
c.wm = b;
b.ac[_.yb(c)] = c;
_.eG(a.A, c)
})
},
u6 = function (a, b) {
_.Wa(b.ac, function (b, d) {
a.A.remove(d)
});
b.ac = {}
},
v6 = function (a) {
var b = a.get("maxIntensity");
return 1 <= b ? b : j6(a.get("data"))
},
w6 = function (a, b) {
b = _.gG(a.A, b);
a.get("projection");
for (var c = 0, d = b.length; c < d; ++c) _.Ac(a.D, b[c].wm)
},
x6 = function (a) {
_.Wa(a.j, function (b,
c) {
_.Ac(a.D, c)
})
},
y6 = function (a) {
var b = a.location || a;
a = a.weight || 1;
return {
ea: new _.I(b.lat(), b.lng()),
weight: a
}
},
z6 = function (a, b, c) {
this.b = a;
a.b = (0, _.p)(this.j, this);
this.A = b;
this.f = c
},
A6 = _.na();
var B6 = "rgba(102, 255, 0, 0);rgba(102, 255, 0, 1);rgba(147, 255, 0, 1);rgba(193, 255, 0, 1);rgba(238, 255, 0, 1);rgba(244, 227, 0, 1);rgba(249, 198, 0, 1);rgba(255, 170, 0, 1);rgba(255, 113, 0, 1);rgba(255, 57, 0, 1);rgba(255, 0, 0, 1)".split(";");
var m6;
var C6, D6 = [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13],
E6 = [0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130];
p6.prototype.getDiv = _.pa("f");
o6.prototype.createImageData = function (a, b) {
for (var c = Array(a * b * 4), d = 0; d < a * b * 4; ++d) c[d] = 0;
return {
data: c,
width: a,
height: b
}
};
o6.prototype.putImageData = function (a) {
var b = this.b,
c = _.Y("img", b.getDiv()),
d = a.width,
e = a.height,
f = a.data,
g = 11 + (4 * d + 1) * e;
a = Array(g + 24);
a[0] = g >>> 24;
a[1] = (g & 16711680) >> 16;
a[2] = (g & 65280) >> 8;
a[3] = g & 255;
a[4] = 73;
a[5] = 68;
a[6] = 65;
a[7] = 84;
a[8] = 8;
a[9] = 29;
a[10] = 1;
g -= 11;
a[11] = g & 255;
a[12] = (g & 65280) >> 8;
a[13] = 255 - a[11];
a[14] = 255 - a[12];
for (var h = 1, l = 0, n = 15, q = 0, r = 0; r < e; ++r) {
a[n++] = 0;
for (var l = l + h, u = 0; u < 4 * d; ++u) a[n++] = f[q], l += h += f[q++]
}
h %= 65521;
l %= 65521;
a[n++] = (l & 65280) >> 8;
a[n++] = l & 255;
a[n++] = (h & 65280) >> 8;
a[n++] = h &
255;
f = n6(a, 4, g + 15);
a[n++] = f >>> 24;
a[n++] = (f & 16711680) >> 16;
a[n++] = (f & 65280) >> 8;
a[n++] = f & 255;
f = 0;
for (g = E6.length; f < g; ++f) a[n++] = E6[f];
if (-1 != d || -1 != e) d = [73, 72, 68, 82, d >>> 24, (d & 16711680) >> 16, (d & 65280) >> 8, d & 255, e >>> 24, (e & 16711680) >> 16, (e & 65280) >> 8, e & 255, 8, 6, 0, 0, 0], e = n6(d, 0, d.length), C6 = "data:image/png;base64," + _.qk(D6.concat(d, [e >>> 24, (e & 16711680) >> 16, (e & 65280) >> 8, e & 255]));
a = C6 + _.qk(a);
c.src = a;
c.width = b.width;
c.height = b.height
};
_.t(q6, _.B);
q6.prototype.radius_changed = function () {
var a = this.get("radius");
_.Gz() ? this.b = 20 > a ? 1 : 2 : this.b = 4;
for (var a = Math.round(a / this.b), b = a / 3, c = [], d = -a; d <= a; d++) c.push(Math.exp(-d * d / (2 * b * b)));
this.f = c
};
_.t(s6, _.yf);
_.k = s6.prototype;
_.k.projection = null;
_.k.getTile = function (a, b, c) {
var d = c.createElement("div");
_.zf(d, this.tileSize);
var e = this.get("opacity");
_.m(e) && _.am(d, e);
a = {
V: d,
zoom: b,
Z: a,
ac: {},
ownerDocument: c
};
d.ma = a;
this.j[_.yb(a)] = a;
t6(this, a);
this.b || (this.b = v6(this));
r6(this.m, a, this.b);
return d
};
_.k.data_changed = function () {
this.f.clear();
var a = this.get("data"),
b = this;
a && (a.forEach(function (a) {
a && _.iJ(b.f, y6(a))
}), this.M());
x6(this);
_.v(this.S, _.z.removeListener);
this.S = [];
a && (this.S = [_.z.bind(a, "insert_at", this, this.si), _.z.bind(a, "remove_at", this, this.ti), _.z.bind(a, "set_at", this, this.eo)])
};
_.k.si = function (a) {
if (a = this.get("data").getAt(a)) a = y6(a), _.iJ(this.f, a), this.M(), w6(this, a.ea)
};
_.k.ti = function (a, b) {
b && (a = y6(b), this.f.remove(a), this.M(), w6(this, a.ea))
};
_.k.eo = function (a, b) {
this.ti(0, b);
this.si(a)
};
_.k.$ = function () {
var a = this.b;
this.b = v6(this);
_.ab(a, this.b) || x6(this)
};
_.k.maxIntensity_changed = function () {
this.b = v6(this);
x6(this)
};
_.k.gradient_changed = function () {
x6(this)
};
_.k.opacity_changed = function () {
var a = this.get("opacity");
_.Wa(this.j, function (b, c) {
_.am(c.V, a)
})
};
_.k.radius_changed = function () {
var a = this;
_.Wa(this.j, function (b, c) {
u6(a, c);
t6(a, c)
});
x6(this)
};
_.k.releaseTile = function (a) {
if (a) {
var b = a.ma;
a.ma = null;
delete this.j[_.yb(b)];
var c = this.A;
_.Wa(b.ac, function (a, b) {
c.remove(b)
});
_.Rl(b.V, "")
}
};
z6.prototype.j = function () {
_.lz(this.f, (0, _.p)(this.m, this))
};
z6.prototype.m = function () {
var a;
a: {
a = this.b.f;
for (var b in a) {
a = a[b];
this.b.remove(a);
break a
}
a = null
}
a && this.A(a)
};
A6.prototype.b = function (a) {
var b = a.j,
c = a.j = a.get("map");
b && (a.b && a.b.unbindAll(), a.f && a.f.release(), _.Wm("Lh", "-p", a));
if (c) {
a.b = new _.Bu({
dissipating: !0,
gradient: B6,
opacity: .6,
radius: 10
});
a.b.bindTo("dissipating", a);
a.b.bindTo("gradient", a);
a.b.bindTo("opacity", a);
a.b.bindTo("radius", a);
b = new _.du(["stringGradient", "opacity"], "colorGradient", function (a, b) {
return l6(a, b)
});
b.bindTo("stringGradient", a.b, "gradient", !0);
var d = new _.du(["radius", "dissipating", "zoom"], "renderingRadius", function (a, b, c) {
return b ?
a : Math.min(Math.round(a * Math.pow(2, c)), 256)
});
d.bindTo("radius", a.b);
d.bindTo("zoom", c);
d.bindTo("dissipating", a.b);
var e = new s6(_.fl.Hm(), function (a, b) {
new z6(a, b, new _.oz(_.nz(250), 0))
});
e.bindTo("projection", c);
e.bindTo("data", a);
e.bindTo("maxIntensity", a);
e.bindTo("gradient", b, "colorGradient");
e.bindTo("radius", d, "renderingRadius");
_.Gz() ? (e.bindTo("opacity", a.b), b.set("opacity", 1)) : b.bindTo("opacity", a.b);
_.QF(c, e, "overlayLayer", 15, function (b) {
a.f = b
});
_.Tm(c, "Lh");
_.Vm("Lh", "-p", a, !!c.b)
}
};
_.mc("visualization_impl", new A6);
});
而这第二个好像和第一个关系密切,在操作数据时调用(字符太多放不下,所以我把它存储在这个fiddle):
https://jsfiddle.net/u59wrb2o/
提前致谢!
这不是确切答案,而是我使用的解决方法,可能对其他人有用
由于找不到这个问题的答案,所以我用了一个技巧,仍然可以访问图例。
简而言之,我让用户使用 HTML 中的滑块定义热图的 maxIntensity 参数(在最左侧时,显示由 Google 定义的默认 maxIntensity 值):
<!-- For the UPPER_BOUND in the max, I chose to use the sum of all my data, it works pretty well -->
<input type="range" id="intensitySlider" onchange="changeMaxIntensity(intensitySlider.value)" min="0" max="UPPER_BOUND" step="1" value="0">
从这里我可以得到现在用这个 JS 函数明确定义的 maxIntensity:
function changeMaxIntensity(maxIntensity) {
// If maxIntensity = 0, it will be set to the default value => heatmap.get('maxIntensity') will return "undefined"
// The "* 1" here is to convert "maxIntensity" from string to number if ever needed
heatmap.set('maxIntensity', maxIntensity * 1);
var maxInt = heatmap.get('maxIntensity'),
valueLegend = document.getElementById("value"),
percentLegend = document.getElementById("percent");
if (maxInt) {
// Not default value (user set != 0)
for (var i = 2; i < 6; i++) {
// The numbers are rounded and formatted in the french way: "1 234 567 Tons" for instance
valueLegend.childNodes[i].textContent = Math.round(maxInt * (i - 1) / 4).toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ") + ' Tons';
percentLegend.childNodes[i].textContent = Math.round(maxInt / globalSalesTons * 100 * (i - 1) / 4).toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ") + ' %';
} else {
// Default value (user set = 0), can't get maxIntensity with .get in this case
valueLegend.childNodes[2].textContent = '...';
valueLegend.childNodes[3].textContent = '...';
valueLegend.childNodes[4].textContent = '...';
valueLegend.childNodes[5].textContent = 'Undefined';
percentLegend.childNodes[2].textContent = '...';
percentLegend.childNodes[3].textContent = '...';
percentLegend.childNodes[4].textContent = '...';
percentLegend.childNodes[5].textContent = 'Undefined';
}
}
有关信息,这是我的 HTML 图例代码:
<div id="legend">
<div class="legend-labels" id ="value">
<div>0 Tons</div><div>...</div><div>...</div><div>...</div><div>Undefined</div>
</div>
<div class="ticks">
<div></div><div></div><div></div><div></div><div></div>
</div>
<div id="legend-gradient" class="grad1"></div>
<div class="ticks">
<div></div><div></div><div></div><div></div><div></div>
</div>
<div class="legend-labels" id ="percent">
<div>0 % of overall sales</div><div>...</div><div>...</div><div>...</div><div>Undefined</div>
</div>
</div>
和 CSS:
.ticks {
display: -ms-flexbox;
display: flex;
-ms-flex-pack: distribute;
justify-content: space-around;
height: 10px;
width: 100%;
background: inherit;
}
.ticks * {
width: 1px;
background: #eeeeee;
}
#legend {
width: 100%;
height: 100px;
background: #333333;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
-ms-flex-align: center;
align-items: center;
color: #eeeeee;
}
.legend-labels {
width: 100%;
height: 25px;
display: -ms-flexbox;
display: flex;
-ms-flex-pack: distribute;
justify-content: space-around;
}
.legend-labels *{
-ms-flex: 1;
flex: 1;
height: 25px;
line-height: 25px;
overflow: hidden;
text-align: center;
}
#legend-gradient {
width: 80%;
height: 30px;
background: YOUR_GRADIENT_HERE;
}
这里有两个截图来说明最终结果:
我想达到的目标
我正在尝试为我的热图的梯度建立图例 - 我使用 GoogleMaps API 成功创建 - 我唯一缺少的是梯度(即在热图上显示最高强度的值)。
我在这个主题上找到了一个很好的主题,它总结并完美地说明了我想要实现的目标,但遗憾的是我感兴趣的部分不起作用:HowTo create legend for google Heatmap?
我试过的
我尝试了几件事(几乎所有我能做的事),包括:
- 使用“heatmap.get('maxIntensity') 属性,但只有在用户事先设置了maxIntensity时才有效,这对我来说是不可能的,因为主要我在使用的数据中可能存在的差异
- 试图找到 maxIntensity 的数学表达式以自己重新计算它
- 深入研究 Google 的 API 以找出他们对我们隐藏的内容(即找到一个类似于上面 link 中给出的解决方案)
- 显然会转到 google 结果的第 10 页,并浏览 Whosebug 上似乎所有相关的主题
问题
所以现在我几乎没有解决方案:也许这里有人知道计算 maxIntensity 的神圣公式,或者比我更了解原始 API 来提取 maxIntensity 值?
什么我"found"
在使用控制台深入研究时,我 认为 我设法隔离了 Google 的 API 参与该过程的部分。它们有点重,但我不能做得更好。
这个显然有一个 属性 标识为 "maxIntensity":
google.maps.__gjsload__('visualization_impl', function (_) {
'use strict';
var i6 = function (a) {
for (var b = Array(a), c = 0; c < a; ++c) b[c] = 0;
for (var c = Array(a), d = 0; d < a; ++d) c[d] = b.concat();
return c
},
j6 = function (a) {
if (!a || !a.getLength()) return 1;
var b = new _.Xd;
a.forEach(function (a) {
a && b.extend(a.location || a)
});
var c = b.f.f,
d = b.b.b,
e = Math.max(b.f.b - c, b.b.f - d);
if (1E-9 > e) {
var f = 0;
a.forEach(function (a) {
a instanceof _.E ? ++f : f += a.weight
});
return Math.max(1, f)
}
var g = 800 / e,
h = i6(800),
l = 1;
a.forEach(function (a) {
if (a) {
var b = a.location || a;
a = a.weight || 1;
b = new _.I(Math.max(0, Math.min(799,
Math.floor((b.lat() - c) * g))), Math.max(0, Math.min(799, Math.floor((b.lng() - d) * g))));
h[b.x][b.y] += a;
l = Math.max(l, h[b.x][b.y])
}
});
return l
},
l6 = function (a, b) {
var c = [],
d = [],
e = 1E3 / (a.length - 1);
_.v(a, function (a, b) {
c.push(b * e);
d.push(_.gJ(a))
});
a = Array(1001);
for (var f = 0, g = 0; 1001 > g; ++g) g > c[f + 1] && ++f, a[g] = f < c.length - 1 ? k6(e * f, g, e * (f + 1), d[f], d[f + 1]) : d[d.length - 1], a[g].alpha *= b, a[g].alpha = _.Za(Math.floor(255 * a[g].alpha), 0, 255);
return a
},
k6 = function (a, b, c, d, e) {
if (a == c) return d;
a = (b - a) / (c - a);
return new _.dJ(Math.floor((e.j -
d.j) * a + d.j), Math.floor((e.f - d.f) * a + d.f), Math.floor((e.b - d.b) * a + d.b), (e.alpha - d.alpha) * a + d.alpha)
},
n6 = function (a, b, c) {
if (!m6) {
for (var d = Array(256), e = 0; 256 > e; ++e) {
for (var f = e, g = 0; 8 > g; ++g) f = f & 1 ? (3988292384 ^ f >>> 1) >>> 0 : f >>> 1;
d[e] = f
}
m6 = d
}
d = 4294967295;
e = b;
for (b += c; e < b; ++e) d = (m6[(d ^ a[e]) & 255] ^ d >>> 8) >>> 0;
return (d ^ 4294967295) >>> 0
},
p6 = function (a) {
this.f = a.createElement("div");
this.b = new o6(this)
},
o6 = _.oa("b"),
q6 = function (a, b) {
this.m = a;
this.b = 1;
this.f = [];
this.j = b
},
r6 = function (a, b, c) {
_.Rl(b.V, "");
var d = b.ownerDocument,
e, f, g, h;
if (_.Gz()) e = g = d.createElement("canvas"), _.$l(e), f = e.getContext("2d"), h = 1 < a.b;
else if (1 == _.W.type && _.Vk(_.W.version, 8)) e = new p6(d), f = e.b, g = e.getDiv(), h = !1;
else return;
e.width = e.height = 256;
b.V.appendChild(g);
e = a.get("projection");
g = a.get("radius");
g = Math.round(g / a.b) * a.b;
var l = 1 << b.zoom,
n = b.ac,
q = (256 + 2 * g) / a.b;
b = i6(q);
for (var r in n)
for (var u = n[r], x = e.fromLatLngToPoint(new _.E(u.K, u.L, !0)), A = e.fromLatLngToPoint(new _.E(u.O, u.P, !0)), x = new _.I(Math.min(x.x, A.x), Math.min(x.y, A.y)), x = new _.I(x.x +
g / l, x.y + g / l), u = a.m.search(u), A = 0, C = u.length; A < C; ++A) {
var D = u[A],
H = e.fromLatLngToPoint(new _.E(D.ea.x, D.ea.y)),
K = Math.floor((Math.floor((H.y - x.y) * l) + g) / a.b),
H = Math.floor((Math.floor((H.x - x.x) * l) + g) / a.b);
0 <= K && K < q && 0 <= H && H < q && (b[K][H] += D.weight)
}
r = a.f;
e = Math.floor(r.length / 2);
g = b.length;
l = g - e;
n = i6(g);
for (q = 0; q < g; ++q)
for (x = b[q], C = n[q], u = 0; u < g; ++u)
if (A = x[u])
for (D = u - e, K = Math.min(l, u + e + 1), H = Math.max(e, D); H < K; ++H) C[H] += A * r[H - D];
b = i6(g - 2 * e);
for (q = 0; q < g; ++q)
for (x = n[q], C = Math.max(e, q - e), D = Math.min(l, q + e + 1),
K = q - e, u = e, H = 0; u < l; ++u, ++H)
if (A = x[u])
for (var G = C; G < D; ++G) b[G - e][H] += A * r[G - K];
r = Math.ceil(256 / a.b);
r = f.createImageData(r, r);
e = a.get("gradient");
g = a.j;
l = e[e.length - 1];
c = e.length / c;
n = r.data;
x = q = 0;
for (u = b.length; x < u; ++x)
for (A = b[x], C = 0, D = A.length; C < D; ++C)(K = A[C]) || e[0].alpha ? (K = e[Math.floor(K * c)] || l, H = g ? K.alpha / 255 : 1, n[q++] = K.j * H, n[q++] = K.f * H, n[q++] = K.b * H, n[q++] = K.alpha) : q += 4;
h ? (d = d.createElement("canvas"), d.width = d.height = 256 / a.b, d.getContext("2d").putImageData(r, 0, 0), f.scale(a.b, a.b), f.drawImage(d, 0,
0)) : f.putImageData(r, 0, 0)
},
s6 = function (a, b) {
_.yf.call(this);
this.tileSize = new _.J(256, 256);
this.j = {};
var c = _.vf(-100, -300, 100, 300);
this.A = new _.dG(c, void 0);
c = _.vf(-90, -180, 90, 180);
this.f = _.jJ(c, function (a, b) {
return a.ea.b(b.ea) && a.weight == b.weight
});
this.S = [];
this.D = new _.zc;
this.b = 0;
this.m = new q6(this.f, a);
this.m.bindTo("projection", this, "projection", !0);
this.m.bindTo("gradient", this, "gradient", !0);
this.m.bindTo("radius", this, "radius", !0);
var d = this;
b(this.D, function (a) {
r6(d.m, a, d.b)
})
},
t6 = function (a,
b) {
var c = b.Z,
d = 1 << b.zoom,
e = a.get("radius"),
f = new _.I(256 * c.x / d, 256 * c.y / d),
c = _.vf((256 * c.x - e) / d, (256 * c.y - e) / d, (256 * (c.x + 1) + e) / d, (256 * (c.y + 1) + e) / d),
d = a.get("projection");
_.kJ(c, d, f, function (c) {
c.wm = b;
b.ac[_.yb(c)] = c;
_.eG(a.A, c)
})
},
u6 = function (a, b) {
_.Wa(b.ac, function (b, d) {
a.A.remove(d)
});
b.ac = {}
},
v6 = function (a) {
var b = a.get("maxIntensity");
return 1 <= b ? b : j6(a.get("data"))
},
w6 = function (a, b) {
b = _.gG(a.A, b);
a.get("projection");
for (var c = 0, d = b.length; c < d; ++c) _.Ac(a.D, b[c].wm)
},
x6 = function (a) {
_.Wa(a.j, function (b,
c) {
_.Ac(a.D, c)
})
},
y6 = function (a) {
var b = a.location || a;
a = a.weight || 1;
return {
ea: new _.I(b.lat(), b.lng()),
weight: a
}
},
z6 = function (a, b, c) {
this.b = a;
a.b = (0, _.p)(this.j, this);
this.A = b;
this.f = c
},
A6 = _.na();
var B6 = "rgba(102, 255, 0, 0);rgba(102, 255, 0, 1);rgba(147, 255, 0, 1);rgba(193, 255, 0, 1);rgba(238, 255, 0, 1);rgba(244, 227, 0, 1);rgba(249, 198, 0, 1);rgba(255, 170, 0, 1);rgba(255, 113, 0, 1);rgba(255, 57, 0, 1);rgba(255, 0, 0, 1)".split(";");
var m6;
var C6, D6 = [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13],
E6 = [0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130];
p6.prototype.getDiv = _.pa("f");
o6.prototype.createImageData = function (a, b) {
for (var c = Array(a * b * 4), d = 0; d < a * b * 4; ++d) c[d] = 0;
return {
data: c,
width: a,
height: b
}
};
o6.prototype.putImageData = function (a) {
var b = this.b,
c = _.Y("img", b.getDiv()),
d = a.width,
e = a.height,
f = a.data,
g = 11 + (4 * d + 1) * e;
a = Array(g + 24);
a[0] = g >>> 24;
a[1] = (g & 16711680) >> 16;
a[2] = (g & 65280) >> 8;
a[3] = g & 255;
a[4] = 73;
a[5] = 68;
a[6] = 65;
a[7] = 84;
a[8] = 8;
a[9] = 29;
a[10] = 1;
g -= 11;
a[11] = g & 255;
a[12] = (g & 65280) >> 8;
a[13] = 255 - a[11];
a[14] = 255 - a[12];
for (var h = 1, l = 0, n = 15, q = 0, r = 0; r < e; ++r) {
a[n++] = 0;
for (var l = l + h, u = 0; u < 4 * d; ++u) a[n++] = f[q], l += h += f[q++]
}
h %= 65521;
l %= 65521;
a[n++] = (l & 65280) >> 8;
a[n++] = l & 255;
a[n++] = (h & 65280) >> 8;
a[n++] = h &
255;
f = n6(a, 4, g + 15);
a[n++] = f >>> 24;
a[n++] = (f & 16711680) >> 16;
a[n++] = (f & 65280) >> 8;
a[n++] = f & 255;
f = 0;
for (g = E6.length; f < g; ++f) a[n++] = E6[f];
if (-1 != d || -1 != e) d = [73, 72, 68, 82, d >>> 24, (d & 16711680) >> 16, (d & 65280) >> 8, d & 255, e >>> 24, (e & 16711680) >> 16, (e & 65280) >> 8, e & 255, 8, 6, 0, 0, 0], e = n6(d, 0, d.length), C6 = "data:image/png;base64," + _.qk(D6.concat(d, [e >>> 24, (e & 16711680) >> 16, (e & 65280) >> 8, e & 255]));
a = C6 + _.qk(a);
c.src = a;
c.width = b.width;
c.height = b.height
};
_.t(q6, _.B);
q6.prototype.radius_changed = function () {
var a = this.get("radius");
_.Gz() ? this.b = 20 > a ? 1 : 2 : this.b = 4;
for (var a = Math.round(a / this.b), b = a / 3, c = [], d = -a; d <= a; d++) c.push(Math.exp(-d * d / (2 * b * b)));
this.f = c
};
_.t(s6, _.yf);
_.k = s6.prototype;
_.k.projection = null;
_.k.getTile = function (a, b, c) {
var d = c.createElement("div");
_.zf(d, this.tileSize);
var e = this.get("opacity");
_.m(e) && _.am(d, e);
a = {
V: d,
zoom: b,
Z: a,
ac: {},
ownerDocument: c
};
d.ma = a;
this.j[_.yb(a)] = a;
t6(this, a);
this.b || (this.b = v6(this));
r6(this.m, a, this.b);
return d
};
_.k.data_changed = function () {
this.f.clear();
var a = this.get("data"),
b = this;
a && (a.forEach(function (a) {
a && _.iJ(b.f, y6(a))
}), this.M());
x6(this);
_.v(this.S, _.z.removeListener);
this.S = [];
a && (this.S = [_.z.bind(a, "insert_at", this, this.si), _.z.bind(a, "remove_at", this, this.ti), _.z.bind(a, "set_at", this, this.eo)])
};
_.k.si = function (a) {
if (a = this.get("data").getAt(a)) a = y6(a), _.iJ(this.f, a), this.M(), w6(this, a.ea)
};
_.k.ti = function (a, b) {
b && (a = y6(b), this.f.remove(a), this.M(), w6(this, a.ea))
};
_.k.eo = function (a, b) {
this.ti(0, b);
this.si(a)
};
_.k.$ = function () {
var a = this.b;
this.b = v6(this);
_.ab(a, this.b) || x6(this)
};
_.k.maxIntensity_changed = function () {
this.b = v6(this);
x6(this)
};
_.k.gradient_changed = function () {
x6(this)
};
_.k.opacity_changed = function () {
var a = this.get("opacity");
_.Wa(this.j, function (b, c) {
_.am(c.V, a)
})
};
_.k.radius_changed = function () {
var a = this;
_.Wa(this.j, function (b, c) {
u6(a, c);
t6(a, c)
});
x6(this)
};
_.k.releaseTile = function (a) {
if (a) {
var b = a.ma;
a.ma = null;
delete this.j[_.yb(b)];
var c = this.A;
_.Wa(b.ac, function (a, b) {
c.remove(b)
});
_.Rl(b.V, "")
}
};
z6.prototype.j = function () {
_.lz(this.f, (0, _.p)(this.m, this))
};
z6.prototype.m = function () {
var a;
a: {
a = this.b.f;
for (var b in a) {
a = a[b];
this.b.remove(a);
break a
}
a = null
}
a && this.A(a)
};
A6.prototype.b = function (a) {
var b = a.j,
c = a.j = a.get("map");
b && (a.b && a.b.unbindAll(), a.f && a.f.release(), _.Wm("Lh", "-p", a));
if (c) {
a.b = new _.Bu({
dissipating: !0,
gradient: B6,
opacity: .6,
radius: 10
});
a.b.bindTo("dissipating", a);
a.b.bindTo("gradient", a);
a.b.bindTo("opacity", a);
a.b.bindTo("radius", a);
b = new _.du(["stringGradient", "opacity"], "colorGradient", function (a, b) {
return l6(a, b)
});
b.bindTo("stringGradient", a.b, "gradient", !0);
var d = new _.du(["radius", "dissipating", "zoom"], "renderingRadius", function (a, b, c) {
return b ?
a : Math.min(Math.round(a * Math.pow(2, c)), 256)
});
d.bindTo("radius", a.b);
d.bindTo("zoom", c);
d.bindTo("dissipating", a.b);
var e = new s6(_.fl.Hm(), function (a, b) {
new z6(a, b, new _.oz(_.nz(250), 0))
});
e.bindTo("projection", c);
e.bindTo("data", a);
e.bindTo("maxIntensity", a);
e.bindTo("gradient", b, "colorGradient");
e.bindTo("radius", d, "renderingRadius");
_.Gz() ? (e.bindTo("opacity", a.b), b.set("opacity", 1)) : b.bindTo("opacity", a.b);
_.QF(c, e, "overlayLayer", 15, function (b) {
a.f = b
});
_.Tm(c, "Lh");
_.Vm("Lh", "-p", a, !!c.b)
}
};
_.mc("visualization_impl", new A6);
});
而这第二个好像和第一个关系密切,在操作数据时调用(字符太多放不下,所以我把它存储在这个fiddle):
https://jsfiddle.net/u59wrb2o/
提前致谢!
这不是确切答案,而是我使用的解决方法,可能对其他人有用
由于找不到这个问题的答案,所以我用了一个技巧,仍然可以访问图例。
简而言之,我让用户使用 HTML 中的滑块定义热图的 maxIntensity 参数(在最左侧时,显示由 Google 定义的默认 maxIntensity 值):
<!-- For the UPPER_BOUND in the max, I chose to use the sum of all my data, it works pretty well -->
<input type="range" id="intensitySlider" onchange="changeMaxIntensity(intensitySlider.value)" min="0" max="UPPER_BOUND" step="1" value="0">
从这里我可以得到现在用这个 JS 函数明确定义的 maxIntensity:
function changeMaxIntensity(maxIntensity) {
// If maxIntensity = 0, it will be set to the default value => heatmap.get('maxIntensity') will return "undefined"
// The "* 1" here is to convert "maxIntensity" from string to number if ever needed
heatmap.set('maxIntensity', maxIntensity * 1);
var maxInt = heatmap.get('maxIntensity'),
valueLegend = document.getElementById("value"),
percentLegend = document.getElementById("percent");
if (maxInt) {
// Not default value (user set != 0)
for (var i = 2; i < 6; i++) {
// The numbers are rounded and formatted in the french way: "1 234 567 Tons" for instance
valueLegend.childNodes[i].textContent = Math.round(maxInt * (i - 1) / 4).toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ") + ' Tons';
percentLegend.childNodes[i].textContent = Math.round(maxInt / globalSalesTons * 100 * (i - 1) / 4).toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ") + ' %';
} else {
// Default value (user set = 0), can't get maxIntensity with .get in this case
valueLegend.childNodes[2].textContent = '...';
valueLegend.childNodes[3].textContent = '...';
valueLegend.childNodes[4].textContent = '...';
valueLegend.childNodes[5].textContent = 'Undefined';
percentLegend.childNodes[2].textContent = '...';
percentLegend.childNodes[3].textContent = '...';
percentLegend.childNodes[4].textContent = '...';
percentLegend.childNodes[5].textContent = 'Undefined';
}
}
有关信息,这是我的 HTML 图例代码:
<div id="legend">
<div class="legend-labels" id ="value">
<div>0 Tons</div><div>...</div><div>...</div><div>...</div><div>Undefined</div>
</div>
<div class="ticks">
<div></div><div></div><div></div><div></div><div></div>
</div>
<div id="legend-gradient" class="grad1"></div>
<div class="ticks">
<div></div><div></div><div></div><div></div><div></div>
</div>
<div class="legend-labels" id ="percent">
<div>0 % of overall sales</div><div>...</div><div>...</div><div>...</div><div>Undefined</div>
</div>
</div>
和 CSS:
.ticks {
display: -ms-flexbox;
display: flex;
-ms-flex-pack: distribute;
justify-content: space-around;
height: 10px;
width: 100%;
background: inherit;
}
.ticks * {
width: 1px;
background: #eeeeee;
}
#legend {
width: 100%;
height: 100px;
background: #333333;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
-ms-flex-align: center;
align-items: center;
color: #eeeeee;
}
.legend-labels {
width: 100%;
height: 25px;
display: -ms-flexbox;
display: flex;
-ms-flex-pack: distribute;
justify-content: space-around;
}
.legend-labels *{
-ms-flex: 1;
flex: 1;
height: 25px;
line-height: 25px;
overflow: hidden;
text-align: center;
}
#legend-gradient {
width: 80%;
height: 30px;
background: YOUR_GRADIENT_HERE;
}
这里有两个截图来说明最终结果: