仿B站顶部鼠标移动效果

本文介绍了一段HTML代码,通过JavaScript实现在网页上,视频背景随鼠标在屏幕左右移动而自动平移。使用`mousemove`事件监听鼠标的移动,并根据X轴位置调整视频的transform属性,实现了流畅的响应效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>嘉门</title>
    <style>
        html,
        body {
            margin: 0px;
            width: 100%;
            position: relative;
            overflow-x: hidden;
        }
        
        .background {
            width: 100%;
            height: 185px;
            z-index: 2;
        }
        
        .video {
            z-index: 1;
            height: auto;
            position: absolute;
        }
        
        video {
            margin-left: -90px;
        }
    </style>
    <script>
        window.onload = function() {
            var ovideo = document.getElementsByTagName("video")[0]; //获取视频赋值给变量
            var oback = document.getElementsByClassName("background")[0]; //获取背景赋值给变量
            oback.onmousemove = function(E) { //鼠标移动获取X轴的方法
                    var xmove = E.screenX;
                    getmouseX(xmove);
                }
                //根据X轴移动背景视频
            function getmouseX(Xmove) { //Xmove为传的xmove的值
                //设置一个变量
                var i = 0;
                //中间值
                var md = document.body.clientWidth / 2; //获取网页宽度除以2
                // console.log(md);
                //根据中间值判断距离
                if (Xmove > md) { //大于中间值,则鼠标在右半区移动
                    var cha = Xmove - md; //cha越大代表需要移动的距离越大
                    var bili = cha / md; //转化比例
                    i = 90 * bili; //移动的距离
                    console.log(Xmove);
                    ovideo.style.transform = "translateX(" + -i + "px)";
                    // console.log(ddd);
                } else if (Xmove < md) { //小于中间值,则鼠标在左半区移动
                    var cha = md - Xmove; //cha越大代表需要移动的距离越大
                    var bili = cha / md; //转化比例
                    i = 90 * bili; //移动的距离
                    console.log(Xmove);
                    ovideo.style.transform = "translateX(" + i + "px)";
                    // console.log(ddd);
                } else {
                    return;
                }
            }
        }
    </script>
</head>

<body>
    <!-- 大框架 -->
    <div class="background">
        <!-- 视频框架 -->
        <div class="video">
            <video src="../img/e71914a7-e5df-43f0-aab0-cbf3ef3b35f5.mp4" autoplay="autoplay" loop muted="muted"></video>
        </div>

    </div>
</body>

</html>

        中途发现b站扒下来的视频加上“autoplay”没法自动播放,之后发现可以通过加上muted="muted"静音播放属性,便可以实现自动播放。

         获取网页宽度时,通过上网查询得知可通过这条语句实现“document.body.clientWidth ”

<think>我们正在使用ZedGraph控件,需要实现当鼠标悬停在折线图的数据点上时,显示该点的数据值。 在ZedGraph中,我们可以通过处理`PointValueEvent`事件来实现。这个事件在鼠标移动到数据点附近时触发,我们可以利用它来显示一个提示框(ToolTip)或者改变数据点的外观(如显示标签)。 根据用户需求,我们主要关注显示数据值,所以我们可以使用ToolTip来显示,也可以考虑在数据点旁边动态添加一个文本标签。 这里提供两种主要方法: 1. 使用ToolTip控件显示数据值(简单,无需修改图形对象) 2. 动态添加文本标签(GraphObj)到图表上(更直观,但需要管理标签的清除) 我们分别实现这两种方法。 方法一:使用ToolTip控件 步骤: a. 在窗体上放置一个ToolTip控件(假设名为toolTip1)。 b. 处理zedGraphControl1的PointValueEvent事件,当事件触发时,设置ToolTip的内容为当前数据点的值,并显示在鼠标位置。 方法二:动态添加文本标签 步骤: a. 同样处理PointValueEvent事件。 b. 在事件中,我们创建一个TextObj对象,设置其位置为数据点的位置(可以稍微偏移),内容为数据值。 c. 注意:在显示新标签前,需要清除之前添加的临时标签(否则会叠加)。我们可以用一个成员变量来记录上一次添加的标签,或者每次清除所有临时标签(通过给标签加一个Tag标识)。 下面分别给出代码示例: 方法一:使用ToolTip ```csharp private void zedGraphControl1_Load(object sender, EventArgs e) { // 初始化图表等操作... // 启用PointValueEvent事件 zedGraphControl1.IsShowPointValues = true; // 设置事件处理 zedGraphControl1.PointValueEvent += new ZedGraphControl.PointValueHandler(MyPointValueHandler); } // 事件处理方法 private string MyPointValueHandler(ZedGraphControl sender, GraphPane pane, CurveItem curve, int iPt) { // 返回要显示的字符串 PointPair point = curve[iPt]; return $"X: {point.X:F2}, Y: {point.Y:F2}"; } ``` 注意:这种方法会使用ZedGraph内置的ToolTip机制,当鼠标悬停在点上时,会在鼠标旁边显示一个提示框。 但是,用户可能想要更醒目的提示,比如在数据点旁边显示一个标签。下面使用方法二。 方法二:动态添加文本标签(并清除之前的标签) 我们用一个成员变量记录上一次添加的标签,以便清除。 ```csharp private TextObj _lastLabel = null; private void zedGraphControl1_PointValueEvent(ZedGraphControl sender, GraphPane pane, CurveItem curve, int iPt) { // 清除上一次添加的标签 if (_lastLabel != null) { pane.GraphObjList.Remove(_lastLabel); _lastLabel = null; } // 获取当前点 PointPair point = curve[iPt]; // 创建文本标签,位置在数据点上方 TextObj label = new TextObj($"Y: {point.Y:F2}", point.X, point.Y + 0.5, CoordType.AxisXYScale); label.FontSpec.Fill = new Fill(Color.White); label.FontSpec.Border.IsVisible = false; label.FontSpec.Angle = 0; // 水平显示 label.Tag = "PointValueLabel"; // 设置一个标签,用于标识 // 添加到面板 pane.GraphObjList.Add(label); _lastLabel = label; // 记录 // 刷新 sender.Invalidate(); return " "; // 返回非空字符串,这样内置的ToolTip也会显示(如果不想显示内置的,可以返回string.Empty) } ``` 但是,上述方法在鼠标离开点时不会清除标签。我们可以再监听鼠标离开事件,当鼠标离开控件时清除标签,但这样会有一个问题:鼠标离开点但还在控件上时,标签仍然存在。 另一种做法:在PointValueEvent事件中,当没有点在鼠标附近时,事件会被触发,此时curve参数为null,我们可以利用这个时机清除标签。 所以修改如下: ```csharp private void zedGraphControl1_PointValueEvent(ZedGraphControl sender, GraphPane pane, CurveItem curve, int iPt) { // 如果curve为null,表示鼠标没有在任何点上 if (curve == null) { if (_lastLabel != null) { pane.GraphObjList.Remove(_lastLabel); _lastLabel = null; sender.Invalidate(); } return string.Empty; } // 清除上一次添加的标签 if (_lastLabel != null) { pane.GraphObjList.Remove(_lastLabel); _lastLabel = null; } // 获取当前点 PointPair point = curve[iPt]; // 创建文本标签,位置在数据点上方 TextObj label = new TextObj($"Y: {point.Y:F2}", point.X, point.Y + 0.5, CoordType.AxisXYScale); label.FontSpec.Fill = new Fill(Color.White); label.FontSpec.Border.IsVisible = false; label.FontSpec.Angle = 0; // 水平显示 label.Tag = "PointValueLabel"; // 设置一个标签,用于标识 // 添加到面板 pane.GraphObjList.Add(label); _lastLabel = label; // 记录 // 刷新 sender.Invalidate(); return $"X: {point.X:F2}, Y: {point.Y:F2}"; // 返回非空字符串,这样内置的ToolTip也会显示(如果不需要内置ToolTip,可以返回string.Empty) } ``` 注意:这里我们同时使用了内置的ToolTip和自定义标签。如果不想显示内置ToolTip,只需返回string.Empty即可。 但是,上述代码在鼠标快速移动时可能会因为频繁的刷新而导致闪烁。我们可以考虑优化,比如使用一个定时器来延迟刷新,但这里为了简单,我们直接使用。 另外,我们还可以考虑使用一个单独的Label控件(放在zedGraphControl外部)来显示数据值,这样就不需要修改图表本身。这种方法类似于ToolTip,但可以自定义位置和样式。 方法三:使用外部Label控件 在窗体上放置一个Label控件(比如叫labelValue),设置其Visible为false,BorderStyle为FixedSingle,BackColor为淡黄色等。 然后在PointValueEvent事件中: ```csharp private void zedGraphControl1_PointValueEvent(ZedGraphControl sender, GraphPane pane, CurveItem curve, int iPt) { if (curve == null) { labelValue.Visible = false; return string.Empty; } PointPair point = curve[iPt]; // 设置标签文本 labelValue.Text = $"X: {point.X:F2}, Y: {point.Y:F2}"; // 设置标签位置(在数据点对应的屏幕坐标处) PointF pt = pane.GeneralTransform(point.X, point.Y, CoordType.AxisXYScale); // 转换为屏幕坐标 Point screenPt = new Point((int)pt.X, (int)pt.Y); screenPt = zedGraphControl1.PointToScreen(screenPt); // 调整位置,避免被鼠标挡住 labelValue.Location = new Point(screenPt.X + 10, screenPt.Y - 20); labelValue.Visible = true; // 返回空字符串,因为我们用外部标签,不需要内置ToolTip return string.Empty; } ``` 同时,我们还需要处理鼠标离开控件的事件来隐藏标签,但ZedGraph的PointValueEvent在鼠标离开点时会传入curve为null,所以我们在上面已经处理了隐藏。 但是,这种方法需要确保标签控件在zedGraphControl的上层(比如放在同一个容器,且ZOrder在上层)。另外,当鼠标移动很快时,标签可能会闪烁。 综合考虑,方法一最简单且内置支持,但样式受限;方法二直接绘制在图表上,效果稳定但需要管理对象;方法三使用外部控件,样式灵活但需要处理坐标转换。 用户可以根据需求选择。 下面我们给出一个完整示例(使用方法一和方法三): 方法一完整示例(内置ToolTip): 这是最简单的,只需设置事件并返回字符串。 方法三完整示例(使用外部Label): 步骤: 1. 在窗体上放置一个Label控件,命名为lblDataPoint,设置Visible=false,设置BackColor为LightYellow,设置AutoSize=true。 2. 编写PointValueEvent事件处理函数。 代码: ```csharp // 在窗体构造函数或Load事件中 zedGraphControl1.PointValueEvent += ZedGraphControl1_PointValueEvent; private string ZedGraphControl1_PointValueEvent(ZedGraphControl sender, GraphPane pane, CurveItem curve, int iPt) { if (curve == null) { lblDataPoint.Visible = false; return string.Empty; } PointPair pt = curve[iPt]; // 将图表坐标转换为屏幕坐标 PointF pixPt = pane.GeneralTransform(pt.X, pt.Y, CoordType.AxisXYScale); // 注意:pixPt是相对于zedGraphControl的坐标 Point screenPoint = sender.Location; screenPoint.Offset((int)pixPt.X, (int)pixPt.Y); // 设置标签位置(稍微偏移) lblDataPoint.Left = screenPoint.X + 10; lblDataPoint.Top = screenPoint.Y - 20; lblDataPoint.Text = $"X: {pt.X:F2}\nY: {pt.Y:F2}"; lblDataPoint.Visible = true; // 返回空字符串,因为我们不使用内置的ToolTip return string.Empty; } ``` 注意:如果鼠标移动很快,可能会发现标签有时不会立即消失,因为curve为null的事件触发可能不够及时。我们可以考虑在鼠标移动事件中处理,但ZedGraph的PointValueEvent已经封装了这些。 另外,当鼠标在数据点之间移动时,curve为null,所以标签会隐藏。 最后,如果用户想要更丰富的显示效果(比如带边框背景等),使用方法二(在图表上绘制)可能更合适。 根据用户需求,我们推荐使用方法一(简单)或方法二(效果稳定)。如果用户需要,我们可以提供方法二的完整实现(带标签管理)。 我们选择方法二作为主要实现,并改进:使用一个固定的Tag来清除所有临时标签,而不是只记录最后一个。因为可能同时有多个标签(比如多个系列),但通常鼠标只能在一个点上,所以一个标签就够了。但为了安全,我们每次清除所有标记为临时标签的对象。 改进方法二: ```csharp private void zedGraphControl1_PointValueEvent(ZedGraphControl sender, GraphPane pane, CurveItem curve, int iPt) { // 清除之前所有标记为"PointValueLabel"的标签 for (int i = pane.GraphObjList.Count - 1; i >= 0; i--) { if (pane.GraphObjList[i].Tag is string tag && tag == "PointValueLabel") { pane.GraphObjList.RemoveAt(i); } } if (curve == null) { sender.Invalidate(); return string.Empty; } PointPair point = curve[iPt]; // 创建文本标签,位置在数据点上方 TextObj label = new TextObj($"Y: {point.Y:F2}", point.X, point.Y + 0.5, CoordType.AxisXYScale); label.FontSpec.Fill = new Fill(Color.White, Color.LightGray, 45.0f); label.FontSpec.Border.IsVisible = true; label.FontSpec.Border.Color = Color.Black; label.FontSpec.Angle = 0; // 水平显示 label.Tag = "PointValueLabel"; // 设置标记 // 添加到面板 pane.GraphObjList.Add(label); // 刷新 sender.Invalidate(); return string.Empty; // 不显示内置ToolTip } ``` 这样,每次鼠标移动到一个新点时,会清除所有之前的标签,然后添加一个新的标签。当鼠标离开点时,标签被清除。 用户可以根据自己的需求调整标签的位置、样式等。 总结:以上提供了三种方法,用户可以根据实际需求选择。最简单的是方法一(内置ToolTip),最稳定且美观的是方法二(动态添加标签),方法三(外部Label)则提供了更多的样式控制但需要处理坐标转换。 我们推荐使用方法二,因为它直接集成在图表中,不会因为控件层次问题而显示不全。 最后,记得在初始化时启用事件: ```csharp zedGraphControl1.IsShowPointValues = true; ``` 如果用户需要,还可以结合之前的高亮显示,比如在鼠标悬停时同时高亮点和显示数值标签。 希望这些方法能帮助用户实现所需功能。</think>### ZedGraph 折线图鼠标悬停显示数据值实现方案 在 ZedGraph 中实现鼠标悬停显示数据值功能,主要有以下三种方法,每种方法都提供完整代码示例: --- #### 方法一:使用内置 ToolTip 功能(推荐) ```csharp // 启用内置ToolTip功能 zedGraphControl1.IsShowPointValues = true; // 自定义ToolTip内容格式 zedGraphControl1.PointValueEvent += (sender, pane, curve, iPt) => { if (curve == null) return string.Empty; PointPair point = curve.Points[iPt]; string tooltip = $"时间: {point.X:HH:mm}\n数值: {point.Y:F2}"; return tooltip; }; // 设置ToolTip样式 zedGraphControl1.PointValueFormat = "F2"; // Y值显示两位小数 zedGraphControl1.PointValueEvent += (sender, pane, curve, iPt) => true; ``` > **优点**:最简单实现方式,自动处理显示位置和隐藏逻辑[^1] --- #### 方法二:自定义浮动标签(更灵活) ```csharp private TextObj _hoverLabel; private void SetupCustomHoverLabel() { zedGraphControl1.MouseMove += (sender, e) => { GraphPane pane = zedGraphControl1.GraphPane; // 清除旧标签 if (_hoverLabel != null) { pane.GraphObjList.Remove(_hoverLabel); _hoverLabel = null; } // 查找最近的数据点 if (zedGraphControl1.FindNearestPoint(e.Location, out CurveItem curve, out int index)) { PointPair point = curve.Points[index]; // 创建新标签 _hoverLabel = new TextObj( $"值: {point.Y:F2}", point.X, point.Y, CoordType.AxisXYScale, AlignH.Center, AlignV.Bottom ); // 设置标签样式 _hoverLabel.FontSpec.Fill = new Fill(Color.White); _hoverLabel.FontSpec.Border.Color = Color.Black; _hoverLabel.FontSpec.Border.IsVisible = true; _hoverLabel.FontSpec.Size = 10; // 添加偏移量避免遮挡 _hoverLabel.Location.AlignH = AlignH.Left; _hoverLabel.Location.X += 0.1; pane.GraphObjList.Add(_hoverLabel); zedGraphControl1.Invalidate(); } }; } ``` > **特点**:完全自定义标签样式和位置,支持更复杂的显示格式 --- #### 方法三:结合数据点高亮显示 ```csharp private void SetupHighlightWithValue() { zedGraphControl1.PointValueEvent += (sender, pane, curve, iPt) => { if (curve is LineItem line) { // 清除所有旧标签 ClearHoverLabels(pane); // 获取数据点 PointPair point = line.Points[iPt]; // 创建值标签 TextObj valueLabel = new TextObj( $"{point.Y:F2}", point.X, point.Y + 0.5, // Y偏移 CoordType.AxisXYScale ); valueLabel.Tag = "hoverLabel"; // 标记为悬停标签 pane.GraphObjList.Add(valueLabel); // 高亮数据点 line.Points[iPt].Color = Color.Red; line.Symbol.Size = 10; zedGraphControl1.Invalidate(); return true; } return false; }; // 添加鼠标离开事件清除标签 zedGraphControl1.MouseLeave += (s, e) => { ClearHoverLabels(zedGraphControl1.GraphPane); zedGraphControl1.Invalidate(); }; } private void ClearHoverLabels(GraphPane pane) { // 清除所有标记的悬停标签 for (int i = pane.GraphObjList.Count - 1; i >= 0; i--) { if (pane.GraphObjList[i].Tag as string == "hoverLabel") { pane.GraphObjList.RemoveAt(i); } } } ``` > **优势**:将数值显示与数据点高亮结合,提升用户体验 --- ### 完整实现示例 ```csharp public void SetupChartWithHover() { GraphPane pane = zedGraphControl1.GraphPane; pane.CurveList.Clear(); // 创建示例数据 double[] x = { 1, 2, 3, 4, 5 }; double[] y = { 10, 15, 7, 20, 12 }; // 添加折线 LineItem line = pane.AddCurve("销售数据", x, y, Color.Blue, SymbolType.Circle); line.Line.Width = 2; line.Symbol.Fill = new Fill(Color.White); line.Symbol.Size = 6; // 方法1:启用内置ToolTip zedGraphControl1.IsShowPointValues = true; zedGraphControl1.PointValueEvent += (s, p, c, i) => $"X: {c.Points[i].X:F1}\nY: {c.Points[i].Y:F2}"; // 方法2:添加自定义浮动标签 SetupCustomHoverLabel(); // 方法3:添加带高亮的数值显示 SetupHighlightWithValue(); // 设置坐标轴 pane.XAxis.Title.Text = "时间"; pane.YAxis.Title.Text = "销量"; pane.Title.Text = "鼠标悬停查看数据值"; zedGraphControl1.AxisChange(); zedGraphControl1.Invalidate(); } ``` --- ### 高级技巧 1. **格式化时间数据**: ```csharp // 使用自定义日期格式 zedGraphControl1.PointValueEvent += (s, p, c, i) => { XDate xDate = new XDate(c.Points[i].X); return $"{xDate.ToString("yyyy-MM-dd HH:mm")}\n值: {c.Points[i].Y:F1}"; }; ``` 2. **多曲线同步显示**: ```csharp zedGraphControl1.PointValueEvent += (s, pane, curve, iPt) => { StringBuilder sb = new StringBuilder(); double xVal = curve.Points[iPt].X; foreach (LineItem line in pane.CurveList) { int idx = line.FindClosestPoint(new PointF((float)xVal, 0)); sb.AppendLine($"{line.Label.Text}: {line.Points[idx].Y:F2}"); } return sb.ToString(); }; ``` 3. **动画效果增强**: ```csharp private void AnimateHover(LineItem line, int index) { // 创建放大动画 System.Timers.Timer timer = new System.Timers.Timer(100); float size = line.Symbol.Size; timer.Elapsed += (s, e) => { size = Math.Min(size + 0.5f, 15f); line.Points[index].Symbol.Size = size; zedGraphControl1.Invoke(new Action(zedGraphControl1.Invalidate)); if (size >= 15f) timer.Stop(); }; timer.Start(); } ``` 4. **防止标签重叠**: ```csharp // 智能调整标签位置 if (pane.YAxis.Scale.Max < point.Y + 2) { valueLabel.Location.Y = point.Y - 1.0; // 如果靠近顶部则显示在下方 } else { valueLabel.Location.Y = point.Y + 0.5; // 默认显示在上方 } ``` --- ### 实现原理 ZedGraph 的悬停显示功能基于以下核心机制: 1. **`PointValueEvent` 事件**:提供鼠标位置对应的数据点索引[^1] 2. **坐标转换**:`GeneralTransform()` 方法将数据坐标转换为屏幕坐标 3. **动态渲染**:`Invalidate()` 强制重绘实现即时更新 4. **对象管理**:`GraphObjList` 存储临时文本标签对象 > **性能提示**:对于大型数据集(>10,000点),建议使用方法一的内置ToolTip,避免频繁重绘图表[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值