信公眾號:Dotnet9,網站:Dotnet9,問題或建議:請網站留言, 如果對您有所幫助:歡迎贊賞。
閱讀導航
YouTube上老外的一個設計,站長覺得不錯,分享給大家作為參考,抽屜菜單的動畫做的非常不錯。
運行起始界面:
站長運行操作一遍,錄制了動畫大家看看:
使用 .NET CORE 3.1 創建名為 “AnimatedMenu” 的WPF模板項目,添加1個Nuget庫:MaterialDesignThemes,版本為最新預覽版3.1.0-ci948。
解決方案主要文件目錄組織結構:
文件【App.xaml】,在 StartupUri 中設置啟動的視圖【MainWindow.xaml】,并在【Application.Resources】節點增加 MaterialDesignThemes庫的樣式文件:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Dark.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Blue.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
文件【MainWindow.xaml】,布局代碼、動畫代碼都在此文件中,源碼如下:
<Window x:Class="AnimatedMenu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" MouseLeftButtonDown="MoveWindow_MouseLeftButtonDown"
Height="600" Width="1024" WindowStyle="None" WindowStartupLocation="CenterScreen">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="0"/>
</WindowChrome.WindowChrome>
<Window.Resources>
<Storyboard x:Key="OpenMenu">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="GridMain">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="250"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="GridMain">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="50"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="StackPanelMenu">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="250"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="listViewItem">
<EasingDoubleKeyFrame KeyTime="0" Value="-250"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="-250"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="listViewItem1">
<EasingDoubleKeyFrame KeyTime="0" Value="-250"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="-250"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.9" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="listViewItem2">
<EasingDoubleKeyFrame KeyTime="0" Value="-250"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="-250"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.1" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="listViewItem3">
<EasingDoubleKeyFrame KeyTime="0" Value="-250"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="-250"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.3" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="listViewItem4">
<EasingDoubleKeyFrame KeyTime="0" Value="-250"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="-250"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="button">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="CloseMenu">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="GridMain">
<EasingDoubleKeyFrame KeyTime="0" Value="250"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="GridMain">
<EasingDoubleKeyFrame KeyTime="0" Value="50"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="StackPanelMenu">
<EasingDoubleKeyFrame KeyTime="0" Value="250"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="ButtonOpenMenu">
<BeginStoryboard Storyboard="{StaticResource OpenMenu}"/>
</EventTrigger>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="ButtonCloseMenu">
<BeginStoryboard x:Name="CloseMenu_BeginStoryboard" Storyboard="{StaticResource CloseMenu}"/>
</EventTrigger>
</Window.Triggers>
<Grid Background="#FF3580BF">
<StackPanel x:Name="StackPanelMenu" Width="250" HorizontalAlignment="Left" Margin="-250 0 0 0" RenderTransformOrigin="0.5,0.5">
<StackPanel.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</StackPanel.RenderTransform>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Height="100" HorizontalAlignment="Center">
<Button Style="{StaticResource MaterialDesignFloatingActionMiniAccentButton}" Background="{x:Null}" BorderBrush="{x:Null}" Padding="0" Width="50" Height="50" Margin="10">
<materialDesign:PackIcon Kind="Settings" Width="40" Height="40"/>
</Button>
<Button x:Name="button" Style="{StaticResource MaterialDesignFloatingActionMiniAccentButton}" BorderBrush="{x:Null}" Padding="0" Width="80" Height="80" Margin="10" RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
<Button.Background>
<ImageBrush ImageSource="https://img.dotnet9.com/logo.png" Stretch="UniformToFill"/>
</Button.Background>
</Button>
<Button Style="{StaticResource MaterialDesignFloatingActionMiniAccentButton}" Background="{x:Null}" BorderBrush="{x:Null}" Padding="0" Width="50" Height="50" Margin="10">
<materialDesign:PackIcon Kind="InformationOutline" Width="40" Height="40"/>
</Button>
</StackPanel>
<ListView>
<ListViewItem x:Name="listViewItem" Height="60" RenderTransformOrigin="0.5,0.5">
<ListViewItem.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</ListViewItem.RenderTransform>
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="Home" Width="30" Height="30" VerticalAlignment="Center" Margin="5"/>
<TextBlock Text="主頁" Margin="10" VerticalAlignment="Center"/>
</StackPanel>
</ListViewItem>
<ListViewItem x:Name="listViewItem1" Height="60" RenderTransformOrigin="0.5,0.5">
<ListViewItem.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</ListViewItem.RenderTransform>
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="AccountSearch" Width="30" Height="30" VerticalAlignment="Center" Margin="5"/>
<TextBlock Text="搜索" Margin="10" VerticalAlignment="Center"/>
</StackPanel>
</ListViewItem>
<ListViewItem x:Name="listViewItem2" Height="60" RenderTransformOrigin="0.5,0.5">
<ListViewItem.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</ListViewItem.RenderTransform>
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="Wechat" Width="30" Height="30" VerticalAlignment="Center" Margin="5"/>
<TextBlock Text="微信" Margin="10" VerticalAlignment="Center"/>
</StackPanel>
</ListViewItem>
<ListViewItem x:Name="listViewItem3" Height="60" RenderTransformOrigin="0.5,0.5">
<ListViewItem.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</ListViewItem.RenderTransform>
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="Qqchat" Width="30" Height="30" VerticalAlignment="Center" Margin="5"/>
<TextBlock Text="QQ" Margin="10" VerticalAlignment="Center"/>
</StackPanel>
</ListViewItem>
<ListViewItem x:Name="listViewItem4" Height="60" RenderTransformOrigin="0.5,0.5">
<ListViewItem.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</ListViewItem.RenderTransform>
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="Facebook" Width="30" Height="30" VerticalAlignment="Center" Margin="5"/>
<TextBlock Text="臉書" Margin="10" VerticalAlignment="Center"/>
</StackPanel>
</ListViewItem>
</ListView>
</StackPanel>
<Grid x:Name="GridMain" Background="#FFFBFBFB" Width="1024" RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Grid.RenderTransform>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1" Background="#FF3580BF">
<Image Height="150" VerticalAlignment="Top" Source="https://dotnet9.com/wp-content/uploads/2017/04/About-Header.jpg" Stretch="UniformToFill"/>
<Ellipse Height="100" Width="100" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="20 100" Stroke="White">
<Ellipse.Fill>
<ImageBrush ImageSource="https://img.dotnet9.com/logo.png" Stretch="UniformToFill"/>
</Ellipse.Fill>
</Ellipse>
<TextBlock Text="Dotnet9" Foreground="White" FontSize="28" FontFamily="Nirmala UI Semilight" Margin="10 100" VerticalAlignment="Top"/>
<StackPanel Margin="0 150">
<Grid Height="60" Margin="20 50 20 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<TextBlock Text="追隨者" VerticalAlignment="Bottom" Foreground="#FFFBFBFB" Margin="5,0,5,5"/>
<TextBlock Text="1.5K" VerticalAlignment="Top" Foreground="#FFFBFBFB" Grid.Row="1" Margin="10 0"/>
<TextBlock Text="跟隨" VerticalAlignment="Bottom" Foreground="#FFFBFBFB" Margin="5,0,5,5" Grid.Column="1"/>
<TextBlock Text="2.3K" VerticalAlignment="Top" Foreground="#FFFBFBFB" Grid.Row="1" Margin="10 0" Grid.Column="1"/>
</Grid>
<TextBlock TextWrapping="Wrap" Margin="10" Foreground="#FFFBFBFB" FontSize="14">
<Run Text="網名:沙漠盡頭的狼"/>
<LineBreak/>
<LineBreak/>
<Run Text="網站:https://dotnet9.com"/>
<LineBreak/>
<Run Text=" Dotnet9的博客 - 一個熱衷于互聯網分享精神的個人博客站點"/>
<LineBreak/>
<LineBreak/>
<Run Text="座右銘:時間如流水,只能流去不流回。"/>
</TextBlock>
</StackPanel>
</Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="ButtonCloseMenu" Style="{StaticResource MaterialDesignFloatingActionMiniAccentButton}" Width="30" Height="30" Padding="0" Background="{x:Null}" BorderBrush="{x:Null}" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5" Click="ButtonCloseMenu_Click" Visibility="Collapsed">
<materialDesign:PackIcon Kind="Menu" Foreground="#FF3580BF"/>
</Button>
<Button x:Name="ButtonOpenMenu" Style="{StaticResource MaterialDesignFloatingActionMiniAccentButton}" Width="30" Height="30" Padding="0" Background="{x:Null}" BorderBrush="{x:Null}" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5" Click="ButtonOpenMenu_Click">
<materialDesign:PackIcon Kind="Menu" Foreground="#FF3580BF"/>
</Button>
<TextBlock Text="照片" Foreground="#FF3580BF" FontSize="30" FontWeight="Bold" Margin="5" Grid.Row="1"/>
<Grid Margin="5" Grid.Row="2" Grid.Column="0">
<Grid.Effect>
<DropShadowEffect BlurRadius="20" Color="#FFEEEEEE" ShadowDepth="1"/>
</Grid.Effect>
<Image Source="https://dotnet9.com/wp-content/uploads/2019/12/wpf.png" Stretch="UniformToFill"/>
<StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<materialDesign:PackIcon Kind="Heart" Foreground="#FFFBFBFB"/>
<TextBlock Text="25" Foreground="#FFFBFBFB"/>
</StackPanel>
</Grid>
<Grid Margin="5" Grid.Row="2" Grid.Column="1">
<Grid.Effect>
<DropShadowEffect BlurRadius="20" Color="#FFEEEEEE" ShadowDepth="1"/>
</Grid.Effect>
<Image Source="https://dotnet9.com/wp-content/uploads/2019/12/winform.png" Stretch="UniformToFill"/>
<StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<materialDesign:PackIcon Kind="Heart" Foreground="#FFFBFBFB"/>
<TextBlock Text="50" Foreground="#FFFBFBFB"/>
</StackPanel>
</Grid>
<Grid Margin="5" Grid.Row="2" Grid.Column="2">
<Grid.Effect>
<DropShadowEffect BlurRadius="20" Color="#FFEEEEEE" ShadowDepth="1"/>
</Grid.Effect>
<Image Source="https://dotnet9.com/wp-content/uploads/2019/12/asp-net-core.png" Stretch="UniformToFill"/>
<StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<materialDesign:PackIcon Kind="Heart" Foreground="#FFFBFBFB"/>
<TextBlock Text="18" Foreground="#FFFBFBFB"/>
</StackPanel>
</Grid>
<Grid Margin="5" Grid.Row="3" Grid.Column="0">
<Grid.Effect>
<DropShadowEffect BlurRadius="20" Color="#FFEEEEEE" ShadowDepth="1"/>
</Grid.Effect>
<Image Source="https://img.dotnet9.com/Xamarin.Forms.png" Stretch="UniformToFill"/>
<StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<materialDesign:PackIcon Kind="Heart" Foreground="#FFFBFBFB"/>
<TextBlock Text="32" Foreground="#FFFBFBFB"/>
</StackPanel>
</Grid>
<Grid Margin="5" Grid.Row="3" Grid.Column="1">
<Grid.Effect>
<DropShadowEffect BlurRadius="20" Color="#FFEEEEEE" ShadowDepth="1"/>
</Grid.Effect>
<Image Source="https://dotnet9.com/wp-content/uploads/2019/12/front-end.png" Stretch="UniformToFill"/>
<StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<materialDesign:PackIcon Kind="Heart" Foreground="#FFFBFBFB"/>
<TextBlock Text="32" Foreground="#FFFBFBFB"/>
</StackPanel>
</Grid>
</Grid>
</Grid>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Height="40" HorizontalAlignment="Right" Margin="10">
<Button Style="{StaticResource MaterialDesignFloatingActionMiniAccentButton}" Width="30" Height="30" Padding="0" Background="{x:Null}" BorderBrush="{x:Null}">
<materialDesign:PackIcon Kind="Bell"/>
</Button>
<Button x:Name="ButtonClose" Style="{StaticResource MaterialDesignFloatingActionMiniAccentButton}" Width="30" Height="30" Padding="0" Background="{x:Null}" BorderBrush="{x:Null}" Click="ButtonClose_Click">
<materialDesign:PackIcon Kind="Close"/>
</Button>
</StackPanel>
</Grid>
</Window>
簡單說明下:
文件【MainWindow.xaml.cs】,后臺關閉窗體、抽屜菜單按鈕切換、窗體移動等事件處理:
private void ButtonClose_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void ButtonOpenMenu_Click(object sender, RoutedEventArgs e)
{
ButtonOpenMenu.Visibility = Visibility.Collapsed;
ButtonCloseMenu.Visibility = Visibility.Visible;
}
private void ButtonCloseMenu_Click(object sender, RoutedEventArgs e)
{
ButtonOpenMenu.Visibility = Visibility.Visible;
ButtonCloseMenu.Visibility = Visibility.Collapsed;
}
private void MoveWindow_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
DragMove();
}
效果圖實現代碼在文中已經全部給出,站長方便演示,文中的圖片使用的本站外鏈圖片,代碼可直接Copy,按解決方案目錄組織代碼文件即可運行。
演示Demo下載
除非注明,文章均由 Dotnet9 整理發布,歡迎轉載。轉載請注明本文地址:https://dotnet9.com/7669.html歡迎掃描下方二維碼關注 Dotnet9 的微信公眾號,本站會及時推送最新技術文章
時間如流水,只能流去不流回!
點擊《【閱讀原文】》,本站還有更多技術類文章等著您哦!!!
itbook 是一款產品文檔構建工具,也可以用于構建個人博客,默認情況下電腦端訪問時左側菜單是展開狀態,可偏偏有人想要實現默認折疊效果,于是誕生了這篇文章!
善良的我選擇幫助別人
可能是網上關于 Gitbook 的教程相對來說有些落后,加上寫文章時分享了不少關于 ,因此關注我的粉絲好友中有不少是來源于 Gitbook.
所以上個月有個好友問我能不能配置 Gitbook 默認折疊的效果,心里有些犯難,作為 gitbook 的忠實粉絲,我都不知道 gitbook 還有這方面的配置?!
但是,善良的我總是有求必應,不忍心拒絕小白用戶,于是我便抱著試一試的心態開始研究一下如何默認折疊?
當然,解決問題前還是要先復現一下問題,然后在命令行中熟練敲入了 gitbook serve 命令來啟動本地服務器,為了排除緩存等影響,特意打開了 Chrome 瀏覽器的無痕模式,果不其然默認左側菜單是展開的!
不能復現的問題都不是我的問題,拒絕解決此類問題,搞不好是你自己環境搭建問題呢!
驀然回首官方文檔已走
問題復現后就要開始尋求解決之道,雖然印象中并沒有相關配置,但是難保記憶混亂遺漏了某些配置項,所以還是先看看官方文檔怎么說的吧!
但是,當你在瀏覽器中輸入 gitbook 官方文檔 時,并找不到想象中的官方文檔而是新版官網,不信你自己去搜一下,肯定是新版官網.
當你自以為找到了官網時,點擊進去查看文檔部分,很遺憾,這是新版文檔并不是老版文檔,你還會繼續百度一下尋求可用鏈接期待找到官方文檔.
為了節省寶貴時間,這里推薦訪問個人維護的 gitbook 文檔
目前提供了中英文兩個語言版本的文檔,相信可以滿足大多數用戶的需求了,選擇任意一種語言后點擊進入翻閱相關設置.
實際上,官方文檔也并沒有什么用,因為根本就沒有提到過如何更改相關配置使其默認折疊而非展開狀態.
官方不再維護舊版文檔,費盡心機找到舊版文檔也無濟于事,因為并沒有提及到相關配置,所以猜測很可能并未提供有關配置項!
百度一下你就知道了嗎
俗話說:"互聯網上絕大多數問題別人都已經遇到過并提供了解決方案,我們唯一要做的就是找到它!"
這也是面向搜索編程的核心思想,遇到默認折疊問題應該也不會例外,那就搜索一下吧!
雖然百度搜索出現了一些相關文章,但是卻不是我們想要的效果,大多數是基于 gitbook 插件實現的目錄折疊效果,并不是默認折疊左側菜單效果.
不管是換關鍵詞重新搜索還是谷歌搜索,均未發現有關默認折疊左側菜單的解決方案,難不成面向搜索失敗了,要做解決問題的第一人嗎?!
多次重復搜索操作均為找到解決方案,由此可見真的很少有人想要默認折疊左側菜單,我也是很佩服提出該問題的小伙伴骨骼驚奇啊!
自力更生找尋蛛絲馬跡
既然依靠別人無法解決問題,那么只能自力更生獨自解決問題,是時候考驗真正的技術了!
為了排除無關干擾,不能再用自己的 gitbook 項目了,畢竟文件太多不方便后續調試,那么不妨重新創建一個測試項目.
雖然一片空白,并沒有什么實質性內容,但是大道至簡,對于我們復現并測試問題來說,足夠了!
打開 Chrome 瀏覽器并按下 F12 開啟調試模式,鼠標選中左側的 Elements 元素選項卡并點亮左側的小鼠標,然后在頁面上找到左側圖標按鈕,于是選中元素高亮了.
單獨摘錄 Html 關鍵代碼如下:
稍微熟悉前端的小伙伴可能很輕松就能明白 a 標簽的 class 屬性表示的含義,見名知意,可以這么解釋:
由此可見,點擊該圖標實現左側菜單折疊/展開效果應該是 .js-toolbar-action 在起作用,也就是說某一段 js 肯定是針對該 class進行了監聽!
此時,點擊右側的 Event Listeners 選項卡查看該元素已監聽的 click 事件,定位到是哪一個具體的 js 文件在起作用.
果不其然,元素上存在 click 點擊事件監聽并且發現執行監聽的邏輯代碼出現在 theme.js 文件,點擊進入文件查看具體內容.
壓縮后的 js 代碼不具備可讀性,點擊左下方的 {} 圖標可以進行代碼格式化,但是可能不是單純的壓縮而是進行了丑化或者混淆代碼之類的邏輯,格式化后的代碼仍然不可讀!
終于發現了蛛絲馬跡,修改的代碼邏輯就隱藏在 theme.js 文件中,只要找到相關源碼重新編譯輸出 theme.js文件并替換應該就能實現默認折疊效果!
不要擔心黎明前的黑暗
根據目前已掌握的線索,可以肯定的是有用線索主要有兩個:
一個是源碼文件,另一個是輸出文件,想要在龐大的 gitbook 項目中迅速定位到相關代碼邏輯,個人能力有限,并不熟悉前端開發調試流程,因此采用最簡單粗暴傻瓜式搜索方式進行排查!
如果讀者對于現代前端開發流程比較屬性的話,大概過一遍項目結構應該就可以調試定位問題了,用不著像我這樣傻瓜式搜索排查!
gitbook 一般安裝在 ~/.gitbook/versions/3.2.3 目錄,其中 ~ 表示用戶家目錄.
選擇一款熟悉的編輯器并打開 Gitbook 安裝目錄,這里以 sublime 編輯器為例,選中項目后右鍵全局搜索關鍵字 js-toolbar-action 期望找到相關源碼文件.
全局搜索后主要出現兩個文件包含 js-toolbar-action 關鍵字,一個是輸出文件 theme.js ,另一個是源碼文件 toolbar.js .
可想而知,源碼文件肯定是經過編譯處理后統一打包輸出,因此不僅僅要找到源碼文件還要掌握如何編譯.
定位到當前 gitbook 目錄后借助全局搜索功能定位到具體的文件路徑,起作用的是 gitbook-plugin-theme-default 項目,其實這就是 Gitbook 的默認主題.
源碼在哪
/Users/snowdreams1006/.gitbook/versions/3.2.3/node_modules/gitbook-plugin-theme-default/src/js/theme/toolbar.js :
粗略看一下,上述代碼是實現觸發左側圖標折疊/展開菜單的邏輯實現,這里只是具體實現還不知道誰是使用者,也就是說這種邏輯是在哪里調用的?
只能繼續順藤摸瓜,往上翻看,根據基本開發常識,在該文件的同級目錄中存在如下文件,其中的 index.js 應該就是入口文件:
打開 index.js 文件,根據注釋我們可以看到 init() 函數是入門函數,其中 sidebar.init() 和 sidebar.toggle() 函數無不說明 sidebar.js 和 toolbar.js 關系密切,完全有理由猜想 sidebar.js 是 toolbar.js 的使用者!
打開 sidebar.js 文件并查看 init() 初始化函數和 toggle() 觸發函數,可以驗證我們的猜想,這里就是控制中心!
: 非手機端初始化上次狀態,默認展開側邊欄,如果是手機端則折疊側邊欄.其中 toggleSidebar() 接收兩個參數,第一次參數表示是展開還是折疊,第二個參數暫不可知.
「: 第一個參數確實表示狀態而第二個參數表示是否有動畫效果,不用看具體代碼邏輯而是看注釋就能猜出大概邏輯了.
通過上述分析,我們可以得知 init() 初始化函數決定了默認行為是折疊還是展開,同時 gitbook.storage.set('sidebar', isOpen()) 和 gitbook.storage.get('sidebar', true) 應該是設置和獲取是否展開菜單的標志!
由此,如果想要默認折疊左側菜單,那么只需要設置成 gitbook.storage.set('sidebar', false) 應該就會生效!
如何編譯
說干就干,于是乎在 init() 函數插入 gitbook.storage.set('sidebar', false) 默認折疊邏輯,接著看一下是否需要重新編譯才能生效?
接著切換到測試項目再次運行 gitbook serve 啟動本地服務器,發現并沒有任何變化,很有可能改變源碼文件需要重新編譯才會生效或者說更改的源碼項目也沒有生效?
: 該源碼文件所在的項目是 gitbook-plugin-theme-default ,根據 gitbook 插件命名規范我們知道,gitbook-plugin-* 一般是功能性插件,這一類的插件有 gitbook-plugin-readmore 閱讀更多插件和 gitbook-plugin-copyright版權保護插件等等.
但是如果插件名以 gitbook-plugin-theme 開頭的話,這一類插件就是主題插件,比如 gitbook-plugin-theme-default 就是默認主題.
除此之外,只要遵守該命名規則的插件引入時無需添加 gitbook-plugin- 前綴,可以直接在 gitbook.json 文件中引入剩余的簡稱作為插件名.
摘錄自 Gitbook 項目的配置文件,可以佐證上述規則的正確性.
作為普通的 nodejs 包,開發規范規定了 package.json 提供了插件的配置信息,而 Gitbook 插件除了是標準的 nodejs 包之外還有自己的約束,主要體現在提供了 gitbook 節點屬性:
默認主題僅僅提供了兩個配置項,分別是 styles 樣式文件位置和 showLevel 是否顯示層級配置.
再一次驗證了猜想的正確性,真的需要修改源碼才能實現默認折疊左側菜單的效果,緊著繼續在 package.json 中找到項目源碼的托管地址,看一下有沒有提供二次開發文檔.
令人遺憾的是,項目介紹空空如也,除了一張主題預覽圖,別的什么都沒有?!
既然沒有二次開發文檔,那就看看項目源碼有沒有別的蛛絲馬跡教我們如何編譯?
繞了這么多,其實還不是因為比較菜,人家都提供給源碼都不會編譯,留下來沒有技術的眼淚!
視角再一次切換到源碼目錄,除了 js 和 less 目錄外,竟然還有一個 build.sh 構建腳本!
這一刻,仿佛看到了九點鐘升起的太陽,未來是你們的也是我們的!
這一段腳本中除了看不懂 browserify,uglifyjs,lessc -clean-css 命令外,剩下部分都很簡單,大致是編譯源碼文件并輸出到 _assets 目錄.
編譯 js 的命令主要有以下兩條,而我們關心的 theme.js 僅涉及到一條,除此之外沒有任何別的依賴,這一點非常好!
接下來的重點就是如何運行 browserify src/js/theme/index.js | uglifyjs -mc > _assets/website/theme.js 命令了!
搖身一變重新編譯源碼
browserify src/js/theme/index.js | uglifyjs -mc > _assets/website/theme.js
百度一下 browserify
再一次打開熟悉的瀏覽器輸入關鍵字 browserify 后出現一系列相關文章,很好奇為啥排名第一個都不會是官網呢?不管怎么樣,找到 browserify 的 github 項目地址也是不錯的!
這里并不關心 browserify 到底是什么,只在乎如何安裝基本環境而已!
如果是 mac 電腦,全局安裝需要管理員權限,應該運行 sudo npm install -g browserify ,如果嫌棄安裝速度慢也可以運行 cnpm install -g browserify ,前提是已安裝 cnpm 命令.
谷歌一下 uglifyjs
不吹不黑,少走一點彎路,直接就找到了 github 項目網址,同樣的也不關心項目介紹,直接翻看如何安裝部分.
重新編譯 others
涉及到 browserify src/js/theme/index.js | uglifyjs -mc > _assets/website/theme.js 命令的兩個插件均已安裝完畢,理所應當開始重新編譯源碼了,但是竟然報錯了?
當出現報錯時,開始懷疑人生,難道推論不正確,難道環境沒有安裝成功嗎,為啥提示找不到 mousetrap 模塊?
算了吧,與其費盡心思猜測為啥無法加載 mousetrap 模塊,不如繼續安裝剩余依賴,最大可能性排除環境問題.
那就先把 src/build.sh 構建腳本涉及到的其他命令全部安裝一遍,然后再試一下吧!
除了編譯 Js 的命令外,還有編譯 Css 的命令,關于構建腳本 build.sh 的其他內容就是基本的復制粘貼之類的操作了.
這里省略面向搜索編程的中間過程,安裝命令如下:
當我再一次運行構建腳本時,滿心期待會編譯成功,沒想到現實再一次打臉,這時候錯誤更多了呢,真的是沒想到!
那就繼續擴大安裝環境范圍,這時候對整個 gitbook-plugin-theme-default 進行 npm install 安裝相關依賴,這一次會發生什么情況呢?
讓我們拭目以待!
命令行沒有了亂七八糟的輸出,世界變得安靜了!
linux 命令行哲學告訴我們,沒有消息就是好消息,全部安裝項目環境后再次運行 src/build.sh 腳本命令行瞬間安靜了!
懷著忐忑不安的心,切換到測試項目運行 gitbook serve 命令后,那一瞬間,感覺世界都靜止了,奇跡就這么發生了?
終于成功了,實現默認折疊效果了嗎?
為了驗證是否成功實現默認折疊失效,做一次反向測試,既然默認折疊左側菜單設置的是 false,如果設置成 true 的話,默認應該是展開狀態.
重新編譯后再次啟動本地測試項目,如果是展開狀態,那就說明成功不是偶然而是靠技巧和努力!
/Users/snowdreams1006/.gitbook/versions/3.2.3/node_modules/gitbook-plugin-theme-default
/Users/snowdreams1006/Documents/workspace/test
苦心人天不負,不是曇花一現的巧合而是貨真價實的現實,就這么實現了默認折疊左側菜單功能!
懶人直達以及回顧總結
如果你是 Gitbook 普通用戶或者懶得折騰,那么推薦你直接替換掉 theme.js 文件:
如果你不怕麻煩,喜歡折騰,那么不妨體驗一下如何重新編譯源碼文件.
值得注意的是,實現默認折疊左側菜單功能僅僅需要添加一行代碼,但是也很有可能和項目中已引入插件存在沖突,畢竟 sidebar 的狀態也可以被未知代碼所更改!Copy// Prepare sidebar: state and toggle buttonfunction init() { // Close sidebar as default state gitbook.storage.set('sidebar', false); // Open sidebar as default state // gitbook.storage.set('sidebar', true); // Init last state if not mobile if (!platform.isMobile()) { toggleSidebar(gitbook.storage.get('sidebar', true), false); } // Close sidebar after clicking a link on mobile $(document).on('click', '.book-summary li.chapter a', function(e) { if (platform.isMobile()) toggleSidebar(false, false); });}
最后希望本文對你有所幫助,面向搜索編程變得不可用時,自力更生也未嘗不可,如果大家在使用 Gitbook 中遇到任何問題,歡迎留言評論告訴我,當然我也不一定保證解決,萬一哪天心血來潮翻看一下源碼就解決了呢!
圖1
圖2
圖2
圖3
圖4
圖5
圖6
「鏈接」
*請認真填寫需求信息,我們會在24小時內與您取得聯系。