如何使自定义滚动条与图表中可见内容成比例?

huangapple go评论54阅读模式
英文:

How to keep a custom scrollbar proportional to the visible content in a graph?

问题

问题描述

我一直在开发一个自定义网格控件,其视口的大小恰好是1024像素,用于绘制信号点。请注意,完整的信号也正好包括1024个点。这意味着一个信号将占据整个网格的宽度。

我还可以对图形进行缩放,这会将信号点的数量乘以缩放因子。具体来说:

const int SignalLength = 1024;
int ZoomFactor = 2; // 用户更新
int NewPoints = SignalLength * ZoomFactor;

我一直在尝试创建自定义的刷子/滚动条,以帮助浏览缩放的信号。然而,在维护滚动和可见内容的比例方面,我一直遇到问题。

可视化示例 [缩放因子:2]

如何使自定义滚动条与图表中可见内容成比例?

我已经处理的一些参数包括:

  • 滚动按钮:每个按钮的大小为50x50像素。

  • 可滚动区域:由于滚动按钮而减小。即Grid宽度 - (50*2)924个像素。

  • 刷子宽度:将始终为可滚动区域 / 缩放因子

请注意图像中的箭头,它显示信号的可见部分与刷子不同步。我猜想刷子移动得比网格实际显示得更快。

代码

private void ZoomFactor_Changed(object sender, EventArgs e)
{
    if (ZoomFactor > 1)
    {
        Scrubber.Width = (ScrubberTrackPanel.Width / ZoomFactor);
        ScrubberWidth.Text = Scrubber.Width.ToString();
        ScrubberTrackPanel.Visible = true;
    }
    else
    {
        ScrubberTrackPanel.Visible = false;
        Scrubber.Width = Scrubber.Parent.Width;
    }
}

private void SfBtn_GridScrollRight_MouseDown(object sender, MouseEventArgs e)
{
   // 左右两个按钮的标签属性都具有步进值。
   // 左侧为-2
   // 右侧为2
   GlobalVars.GridScrubStepSize = 0 + int.Parse((SfButton)sender).Tag.ToString());
   GridScrubberTimer.Start();
}

private void GridScrubberTimer_Tick(object sender, EventArgs e)
{
    ScrollGrid(GlobalVars.GridScrubStepSize);
}

private void ScrollGrid(int StepSize)
{
   var newStepPos = GlobalVars.ZoomedSignalLeft + StepSize;
   // 如果到达图的边界(左/右)之一,停止滚动定时器。
   if (newStepPos <= 0 || newStepPos >= 1024 * ZoomFactor && GridScrubberTimer.Enabled)
   {
       GridScrubberTimer.Stop();
       return;
   }
   var ZoomedSignalSlice = GlobalVars.ZoomedSignal.Skip(newStepPos).Take(1024).ToList();
   if (ZoomedSignalSlice.Count == 1024)
   {
       GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrubStepSize;
       if (ScrubberTrackPanel.Visible)
       {
           Scrubber.Location = new Point(Scrubber.Location.X + (int)Math.Floor(GlobalVars.GridScrubStepSize/ (float)ZoomFactor), 0);
           ScrubberCords.Text = Scrubber.Location.ToString();
       }
       GraphGrid.Refresh();
   }
}

尝试的解决方案

我尝试了如何计算滚动条拇指的大小https://stackoverflow.com/questions/22035363/formula-for-content-step-of-scrollbar,但不知何故,我无法正确把握比例。

我确定自己漏掉了一些非常明显的(并且愚蠢的:p)东西,您将在其中提供指导。
1: https://i.stack.imgur.com/mBGwO.png
2: https://stackoverflow.com/questions/16366795/how-to-calculate-the-size-of-scroll-bar-thumb
3: https://stackoverflow.com/questions/22035363/formula-for-content-step-of-scrollbar

英文:

Problem Statement

I've been working on a custom grid control whose viewport is exactly of size 1024 pixels which is used to plot signal points. Note that a complete signal also consist of exactly 1024 points. This means that one signal spread to the whole width of the grid.

I can also zoom into the graph which increases the Signal points times ZoomFactor. which is:

...
const int SignalLength = 1024;
int ZoomFactor = 2;    //Updated by user
int NewPoints = SignalLength * ZoomFactor;
...

I've been trying to create custom scrubber/scroller which helps in scrolling through a zoomed signal. However, I've been facing issues during maintaining the proportions of scroll and visible content in sync.


Visual Example [ZoomFactor: 2]

如何使自定义滚动条与图表中可见内容成比例?

A few parameters that I've worked are:

  • Scroll Buttons : Each of Size 50x50 pixels

  • Scrollable Area: Which reduces due to Scroll buttons. That is Grid Width - (50*2): 924 pixels.

  • Scrubber Width : Which will always be Scrollable Area / ZoomFactor

Notice the arrows in image which shows the visible section of signal is not in sync with the scrubber. I guess the scrubber is moving too fast than what the grid is actually showing.


Code

private void ZoomFactor_Changed(object sender, EventArgs e)
{
    if (ZoomFactor &gt; 1)
    {
        Scrubber.Width = (ScrubberTrackPanel.Width / ZoomFactor);
        ScrubberWidth.Text = Scrubber.Width.ToString();
        ScrubberTrackPanel.Visible = true;
    }
    else
    {
        ScrubberTrackPanel.Visible = false;
        Scrubber.Width = Scrubber.Parent.Width;
    }
}

private void SfBtn_GridScrollRight_MouseDown(object sender, MouseEventArgs e)
{
   // Both left and right button&#39;s tag property have the step value.
   // Left has -2 
   // Right has 2
   GlobalVars.GridScrubStepSize = 0 + int.Parse((SfButton)sender).Tag.ToString());
   GridScrubberTimer.Start();
}

private void GridScrubberTimer_Tick(object sender, EventArgs e)
{
    ScrollGrid(GlobalVars.GridScrubStepSize);
}

private void ScrollGrid(int StepSize)
{
   var newStepPos = GlobalVars.ZoomedSignalLeft + StepSize;
   //To stop scroll timer if any of the boundry (left/right) of graph is reached.
   if (newStepPos &lt;= 0 || newStepPos &gt;= 1024 * ZoomFactor &amp;&amp; GridScrubberTimer.Enabled)
   {
       GridScrubberTimer.Stop();
       return;
   }
   var ZoomedSignalSlice = GlobalVars.ZoomedSignal.Skip(newStepPos).Take(1024).ToList();
   if (ZoomedSignalSlice.Count == 1024)
   {
       GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrubStepSize;
       if (ScrubberTrackPanel.Visible)
       {
           Scrubber.Location = new Point(Scrubber.Location.X + (int)Math.Floor(GlobalVars.GridScrubStepSize/ (float)ZoomFactor), 0);
           ScrubberCords.Text = Scrubber.Location.ToString();
       }
       GraphGrid.Refresh();
   }
}

Tried Solutions

I've tried How to calculate the size of scroll bar thumb and https://stackoverflow.com/questions/22035363/formula-for-content-step-of-scrollbar but somehow I'm not able to grasp the proportions correctly.

I'm sure I'm missing something very obvious (&& stupid :p) thing which you will shed light on.

答案1

得分: 1

在经过数小时的代码调试后,我意识到位置计算完全错误。在修复后,滚动功能按预期工作,并适当地保持了比例。

以下是正确的代码:

...
GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrollStepSize;
// 将可见信号在网格上的当前起始位置映射到ScrollerTrackPanel范围内,然后除以ZoomFactor以获得在网格上可见信号图像上刮板位置与可见信号的比例位置。
int newx = (int)Math.Floor(GlobalVars.ZoomedSignalLeft / 1024F * ScrollerTrackPanel.Width / ZoomFactor);
Scrubber.Location = new Point(newx, 0);
...
英文:

After tinkering a lot with the code for hours I realized the calculation for the location was very wrong. After fixing it, the scroll is working as expected while maintaining the proportions appropriately.

Below is the correct code:

...
GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrollStepSize;
// Mapping the current beginning position of the visible signal on the grid in the range of ScrollerTrackPanel and then dividing 
// it with the ZoomFactor To get location of scrubber over the signal image proportional to the visible signal on the grid.
int newx = (int)Math.Floor(GlobalVars.ZoomedSignalLeft / 1024F * ScrollerTrackPanel.Width / ZoomFactor);
Scrubber.Location = new Point(newx, 0);
...

huangapple
  • 本文由 发表于 2023年3月1日 14:37:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75600277.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定