📊 报价费率模型可视化 V1.0
基于 quotation_model_v1.0.json · 36个历史项目 + 5个投标案例 · 按工程类型分组展示设计费/施工费/监理费费率
📈 设计费费率对比 按工程类型
典型费率
费率下限
费率上限
📈 施工建安费费率对比 按工程类型
典型费率
费率下限
费率上限
📈 监理费费率对比 按工程类型
典型费率
费率下限
费率上限
📋 费率明细表 N/A
| 工程类型 | 描述 | 设计费率(%) | 施工费率(%) | 监理费率(%) | 样本数 | 投资规模分级 |
// ===== 科技风高级感粒子动画(增强版) =====
// 在base粒子动画加载完成后运行,替换为更丰富的粒子效果
(function(){
var _origInit = window.addEventListener;
var enhancedReady = false;
function initEnhancedParticles() {
if (enhancedReady) return;
enhancedReady = true;
// Hide the base canvas - we'll use our own
var baseCanvas = document.getElementById('particleCanvas');
if (baseCanvas) {
baseCanvas.style.opacity = '0.15';
}
// Create enhanced canvas
var canvas = document.createElement('canvas');
canvas.id = 'techParticleCanvas';
canvas.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:-1;pointer-events:none;display:block;';
document.body.insertBefore(canvas, document.body.firstChild);
var ctx = canvas.getContext('2d');
var particles = [];
var stars = [];
var w, h;
var mouse = { x: -9999, y: -9999 };
function resize() {
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
}
resize();
window.addEventListener('resize', resize);
// Mouse tracking
document.addEventListener('mousemove', function(e) {
mouse.x = e.clientX;
mouse.y = e.clientY;
});
document.addEventListener('mouseleave', function() {
mouse.x = -9999;
mouse.y = -9999;
});
// Create particles
var particleCount = Math.min(160, Math.floor(w * h / 10000));
var colorPalette = [
{ r: 14, g: 165, b: 233 }, // cyan
{ r: 56, g: 189, b: 248 }, // light blue
{ r: 139, g: 92, b: 246 }, // purple
{ r: 6, g: 182, b: 212 }, // teal
];
for (var i = 0; i < particleCount; i++) {
var c = colorPalette[Math.floor(Math.random() * colorPalette.length)];
particles.push({
x: Math.random() * w,
y: Math.random() * h,
vx: (Math.random() - 0.5) * 0.6,
vy: (Math.random() - 0.5) * 0.6,
r: Math.random() * 2 + 0.8,
color: c,
alpha: Math.random() * 0.4 + 0.15,
pulseSpeed: Math.random() * 0.02 + 0.005,
pulsePhase: Math.random() * Math.PI * 2,
origR: 0
});
particles[i].origR = particles[i].r;
}
// Create background stars
for (var i = 0; i < 60; i++) {
stars.push({
x: Math.random() * w,
y: Math.random() * h,
r: Math.random() * 0.8 + 0.2,
alpha: Math.random() * 0.3 + 0.05,
twinkleSpeed: Math.random() * 0.03 + 0.01,
twinklePhase: Math.random() * Math.PI * 2
});
}
var frame = 0;
function draw() {
frame++;
ctx.clearRect(0, 0, w, h);
// Draw background stars
for (var i = 0; i < stars.length; i++) {
var s = stars[i];
var twinkle = Math.sin(frame * s.twinkleSpeed + s.twinklePhase) * 0.5 + 0.5;
ctx.beginPath();
ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(56, 189, 248, ' + (s.alpha * twinkle) + ')';
ctx.fill();
}
// Sort particles by y for depth effect when drawing connections
// (skip sorting for performance, just use normal order)
// Draw connections between nearby particles
for (var i = 0; i < particles.length; i++) {
for (var j = i + 1; j < particles.length; j++) {
var p1 = particles[i];
var p2 = particles[j];
var dx = p1.x - p2.x;
var dy = p1.y - p2.y;
var dist = Math.sqrt(dx*dx + dy*dy);
var connectDist = 160;
if (dist < connectDist) {
var alpha = 0.08 * (1 - dist / connectDist);
// If mouse is nearby, glow connections closer to mouse
var mx = mouse.x;
var my = mouse.y;
var nearMouse1 = Math.sqrt(Math.pow(p1.x - mx, 2) + Math.pow(p1.y - my, 2));
var nearMouse2 = Math.sqrt(Math.pow(p2.x - mx, 2) + Math.pow(p2.y - my, 2));
if (nearMouse1 < 300 || nearMouse2 < 300) {
alpha = alpha * 1.5;
}
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
// Gradient colored lines
var grad = ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);
var c1 = p1.color;
var c2 = p2.color;
grad.addColorStop(0, 'rgba(' + c1.r + ',' + c1.g + ',' + c1.b + ',' + alpha + ')');
grad.addColorStop(1, 'rgba(' + c2.r + ',' + c2.g + ',' + c2.b + ',' + alpha + ')');
ctx.strokeStyle = grad;
ctx.lineWidth = 0.6;
ctx.stroke();
}
}
}
// Draw and update particles
for (var i = 0; i < particles.length; i++) {
var p = particles[i];
// Movement
p.x += p.vx;
p.y += p.vy;
// Wrap around edges
if (p.x < -10) p.x = w + 10;
if (p.x > w + 10) p.x = -10;
if (p.y < -10) p.y = h + 10;
if (p.y > h + 10) p.y = -10;
// Slight random perturbation for organic feel
p.vx += (Math.random() - 0.5) * 0.02;
p.vy += (Math.random() - 0.5) * 0.02;
// Limit velocity
var speed = Math.sqrt(p.vx*p.vx + p.vy*p.vy);
if (speed > 0.8) {
p.vx = (p.vx / speed) * 0.8;
p.vy = (p.vy / speed) * 0.8;
}
// Mouse interaction - gentle attraction
var mx = mouse.x;
var my = mouse.y;
var distToMouse = Math.sqrt(Math.pow(p.x - mx, 2) + Math.pow(p.y - my, 2));
if (distToMouse < 250 && distToMouse > 0) {
var force = (250 - distToMouse) / 250 * 0.02;
p.vx += (mx - p.x) / distToMouse * force;
p.vy += (my - p.y) / distToMouse * force;
p.r = p.origR * (1 + (1 - distToMouse/250) * 0.8);
} else {
p.r = p.origR;
}
// Pulse effect
var pulse = Math.sin(frame * p.pulseSpeed + p.pulsePhase) * 0.3 + 0.7;
var drawAlpha = p.alpha * pulse;
// Draw glow
var grad = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.r * 3);
var c = p.color;
grad.addColorStop(0, 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + drawAlpha + ')');
grad.addColorStop(0.3, 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + drawAlpha * 0.3 + ')');
grad.addColorStop(1, 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',0)');
ctx.beginPath();
ctx.arc(p.x, p.y, p.r * 3, 0, Math.PI * 2);
ctx.fillStyle = grad;
ctx.fill();
// Draw core
ctx.beginPath();
ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + (drawAlpha * 1.2) + ')';
ctx.fill();
}
requestAnimationFrame(draw);
}
draw();
}
// Wait for page fully loaded including base particle script
if (document.readyState === 'complete') {
setTimeout(initEnhancedParticles, 200);
} else {
window.addEventListener('load', function() {
setTimeout(initEnhancedParticles, 200);
});
}
})();