zoukankan      html  css  js  c++  java
  • 基于CefSharp开发浏览器(六)浏览器网页缩放

    一、网页缩放分析

    缩放入口

    1、Ctrl + 鼠标滑轮缩放

    2、菜单中缩放子菜单缩放

    3、搜索框中网页缩放按钮缩放

    缩放属性及命令

    ChromiumWebBrowser 提供了缩放量值、缩放级别、放大/缩小/重置命令等,如下图

     

    二、鼠标滑轮缩放

    简单缩放实现

    要实现缩放,首先需捕获鼠标滚动事件,在初始化WebBrowser方法中增加

     this.CefWebBrowser.PreviewMouseWheel += CefWebBrowser_PreviewMouseWheel;

    并实现CefWebBrowser_PreviewMouseWheel方法,这里需要判断Ctrl是否按下,代码如下:

    private void CefWebBrowser_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if ((Keyboard.Modifiers & ModifierKeys.Control) != ModifierKeys.Control) return;
        try
        {
            if (e.Delta > 0)
            {
                CefWebBrowser.ZoomInCommand.Execute(null);
            }
            else if (e.Delta < 0)
            {
                CefWebBrowser.ZoomOutCommand.Execute(null);
            }
            e.Handled = true;
        }
        catch (Exception ex)
        {
    
        }
    }

    其中e.Delta大于0时放大网页,小于0时缩小网页

    页面重置

    一般习惯Ctrl+0重置网页大小,故需要在CefWebBrowser_PreviewKeyDown中增加组合键处理,注意:0的key值包含小键盘(NumPad0),代码如下:

    if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control
                   && (e.Key == Key.D0 || e.Key == Key.NumPad0))
    {
        CefWebBrowser.ZoomResetCommand.Execute(null);
        // CefWebBrowser.SetZoomLevel(0);
    }

    ZoomResetCommand 可使缩放级别恢复到页面打开时的缩放级别(默认为100%,若有设置可能不是100%),强势重置到100%可使用注释代码 CefWebBrowser.SetZoomLevel(0);

    三、增加缩放级别显示

    上面内容已可以实现网页缩放,但不知具体缩放比例(级别),查看Edge缩放展示

    当网页缩放时会在搜索框中显示缩放按钮,并在下方展示缩放小窗口,接下来实现如下内容

    1、扩展搜索框

     由于搜索框的内容将越来越多,故不能用通用的MTextBox,需新建一个搜索框便于以后内容扩展,新建CustomControl MSearchText,

    并从MTextBox搬砖到MSearchText

     MSearchText控件需要增加依赖属性ZoomLevelType用来判断缩放按钮是否显示、缩小、放大

    此时需要个Menu类型,添加枚举类型 None不显示缩放

    public enum ZoomType
    {
        None,
        In,
        Out,
    }

    增加依赖属性

    public static readonly DependencyProperty ZoomLevelTypeProperty = DependencyProperty.Register("ZoomLevelType", typeof(ZoomType), typeof(MSearchText));
    /// <summary>
    /// ZoomLevelType 缩放类型
    /// </summary>
    public ZoomType ZoomLevelType
    {
        get => (ZoomType)GetValue(ZoomLevelTypeProperty);
        set => SetValue(ZoomLevelTypeProperty, value);
    }

    在Xaml中Search框中增加一列 ZoomButon

     <Grid Grid.Column="2">
          <ToggleButton x:Name="PART_ZoomButton" FontSize="16" Style="{DynamicResource ToggleButton.FontButton}" Margin="2,0"/>
     </Grid>

    在触发器中增加显示状态控制

    <Trigger Property="ZoomLevelType" Value="None">
        <Setter TargetName="PART_ZoomButton" Property="Visibility" Value="Collapsed" />
    </Trigger>
    <Trigger Property="ZoomLevelType" Value="In">
        <Setter TargetName="PART_ZoomButton" Property="Content" Value="&#xe678;" />
    </Trigger>
    <Trigger Property="ZoomLevelType" Value="Out">
        <Setter TargetName="PART_ZoomButton" Property="Content" Value="&#xe620;" />
    </Trigger>

    2、ZoomLevelType 类型绑定

    在MSearchText 中增加Binding,ViewModel这里不再赘述。

     <controls:MSearchText Grid.Column="1" Watermark="搜索或输入Web地址" Text="{Binding CurrentUrl, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
                                          ZoomLevelType="{Binding ZoomLevelType}" KeyDown="Search_OnKeyDown"/>

    当页面缩放时,执行SetSearchZoomStatus方法

    private void SetSearchZoomStatus()
    {
        if (CefWebBrowser.ZoomLevel < 0)
        {
            ViewModel.ZoomLevelType = ZoomType.Out;
        }
        else if (CefWebBrowser.ZoomLevel > 0)
        {
            ViewModel.ZoomLevelType = ZoomType.In;
        }
        else
        {
            ViewModel.ZoomLevelType = ZoomType.None;
        }
    }

    运行效果:

    3、 缩放小窗口

    Edge缩放小窗口具有如下特点:

    1、缩放比例实时更新

    2、当点击缩放Button 弹出小窗口

    3、Ctrl+鼠标滑轮放大缩小 小窗口几秒后消失

    首先设计小窗口,采用Popup,继续扩展MSearchText,增加Popup弹窗,增加TextBlock用于显示缩放比例,三个Button分别为缩小、放大、重置

    <Popup x:Name="PART_ZoomPopUp" PopupAnimation="Fade" Placement="Bottom" PlacementTarget="{Binding ElementName=PART_ZoomButton}"
           StaysOpen="{TemplateBinding ZoomStaysOpen}" AllowsTransparency="True" HorizontalOffset="-180" VerticalOffset="5" IsOpen="{TemplateBinding ZoomIsChecked}">
        <Border Background="{DynamicResource WebBrowserBrushes.SearchZoomPopupBackground}" CornerRadius="5">
            <DockPanel Width="251" Height="40">
                <TextBlock Text="{TemplateBinding ZoomRatio}" VerticalAlignment="Center" Margin="15,0,0,0" HorizontalAlignment="Left"/>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,15,0">
                    <Button Content="&#xe60c;" Style="{DynamicResource Button.FontButton}" Width="26" Height="26"/>
                    <Button Content="&#xe699;" Style="{DynamicResource Button.FontButton}" Margin="10,0,0,0" Width="26" Height="26"/>
                    <Button Content="重置" Style="{DynamicResource Button.FontButton}" Margin="10,0,0,0" Width="64" Background="{DynamicResource WebBrowserBrushes.SearchZoomPopupResetBackground}"/>
                </StackPanel>
            </DockPanel>
        </Border>
    </Popup>

     Popup的 PlacementTarget指向缩放按钮。此时缩放按钮代码如下:

    <ToggleButton xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  x:Name="PART_ZoomButton" FontSize="16" 
    Style
    ="{DynamicResource ToggleButton.FontButton}" IsChecked="{TemplateBinding ZoomIsChecked}" Margin="2,0"/>

    根据特点1,需要添加依赖属性ZoomRatio用于实时刷新比例,

    根据特点2 和特点3 缩放按钮的选中状态需控制,故增加依赖属性 ZoomIsChecked,

    同时需要控制Popup的显示是否保持显示状态,故增加依赖属性 ZoomStaysOpen,

    在ViewModel中同样需要增加上述属性(非依赖属性)

    接着对MSearchText使用处建立绑定如下:

    <controls:MSearchText Grid.Column="1" Watermark="搜索或输入Web地址" Text="{Binding CurrentUrl, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
                          ZoomLevelType="{Binding ZoomLevelType}" ZoomRatio="{Binding ZoomRatio}" ZoomIsChecked="{Binding ZoomIsChecked}"
                          ZoomStaysOpen="{Binding ZoomStaysOpen}"  KeyDown="Search_OnKeyDown"/>

    4、后端代码控制

    扩展SetSearchZoomStatus方法,增加对选中状态及显示比例(显示比例做了简单处理,并不完全正确)的控制

    private void SetSearchZoomStatus()
    {
        if (CefWebBrowser.ZoomLevel < 0)
        {
            ViewModel.ZoomLevelType = ZoomType.Out;
            ViewModel.ZoomIsChecked = true;
            if (CefWebBrowser.ZoomLevel > -1)
            {
                ViewModel.ZoomRatio = "90%";
            }
            else if (CefWebBrowser.ZoomLevel <= 1)
            {
                var radio = Math.Round((CefWebBrowser.ZoomLevel + 5) / 5 * 100);
                ViewModel.ZoomRatio = $"{radio}%";
            }
        }
        else if (CefWebBrowser.ZoomLevel > 0)
        {
            ViewModel.ZoomLevelType = ZoomType.In;
            ViewModel.ZoomIsChecked = true;
            var radio = Math.Round((1 + CefWebBrowser.ZoomLevel) * 100, 2);
            ViewModel.ZoomRatio = $"{radio}%";
        }
        else
        {
            ViewModel.ZoomLevelType = ZoomType.None;
            ViewModel.ZoomIsChecked = false;
        }
    
    }

    接着增加定时器,在鼠标滑轮放大时启动定时器,用于判断Popup是否消失,

    此处用一变量_zoomWaitingCount判断是否隐藏,如持续滚动滑动则_zoomWaitingCount重新计数

    private void CefWebBrowser_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if ((Keyboard.Modifiers & ModifierKeys.Control) != ModifierKeys.Control)
        {
            ViewModel.ZoomStaysOpen = false;
            return;
        }
        try
        {
            _zoomWaitingCount = 0;
            if (e.Delta > 0)
            {
                if (this.CefWebBrowser.ZoomLevel < 4)
                {
                    CefWebBrowser.ZoomInCommand.Execute(null);
                }
                ViewModel.ZoomStaysOpen = true;
            }
            else if (e.Delta < 0)
            {
                if (this.CefWebBrowser.ZoomLevel > -4)
                {
                    CefWebBrowser.ZoomOutCommand.Execute(null);
                }
                ViewModel.ZoomStaysOpen = true;
            }
            _zoomToolTimer.Elapsed -= ZoomToolTimer_Elapsed;
            _zoomToolTimer.Elapsed += ZoomToolTimer_Elapsed;
            _zoomToolTimer.AutoReset = true;
            _zoomToolTimer.Enabled = true;
            SetSearchZoomStatus();
            e.Handled = true;
        }
        catch (Exception ex)
        {
    
        }
    }
    
    private void ZoomToolTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (_zoomWaitingCount > 2)
        {
            _zoomToolTimer?.Stop();
            ViewModel.ZoomIsChecked = false;
            ViewModel.ZoomStaysOpen = false;
            _zoomWaitingCount = -1;
            return;
        }
    
        if (_zoomWaitingCount > -1)
        {
            _zoomWaitingCount++;
        }
    }

     运行效果:

    小弹窗按钮命令绑定这里不再赘述,详情请查看代码

    四、源码地址

    gitee地址:https://gitee.com/sirius_machao/mweb-browser

  • 相关阅读:
    那些年坑爹的JS题目
    CSS(十三).高度如何铺满全屏
    JS模式和原型精解
    CSS(十二).transition的应用之CSS中心扩散
    一些值得记录的面试题
    随笔
    原生Ajax实现
    code和pre竟然有区别!!!!
    原生JS轮播-各种效果的极简实现(二)面向对象版本的实现和优化
    原生JS轮播-各种效果的极简实现
  • 原文地址:https://www.cnblogs.com/mchao/p/14086441.html
Copyright © 2011-2022 走看看