們在瀏覽網頁時或者翻轉頁面時,經常會看到很多精美的效果的效果。其中,抽屜式網頁效果比較常見,它主要由圖片和文字通過添加浪js 來實現。抽屜式網頁通過移動鼠標來實現頁面的切換,通過改變文字和圖片而展現不同的界面,它非常實用而且實現簡單。
解決方案
制作抽屜式頁面時,主要會用倒忙HTML , CSS 和 JavaScript 。
(1)通過 div 來規定主要內容部分占據的大小,并通過 CSS 來修正。
(2)使用 overflow 標簽,使得多余的圖片部分隱藏。
(3)通過 js 來實現圖片的移動。
制作過程:
( 1 )為網頁添加背景圖片,并定義一個容器 wrap 來規定網頁主要內容的大小和它占據的位置,如圖 1 所示。
<div id="wrap">
</div>
*{
margin: 0;
padding: 0;
}
body{
background: url(img/sfq4.jpg) center top no-repeat;
}
#wrap{
width: 1090px;
height: 429px;
margin: 150px auto;
border: 1px solid red;
}
( 2 )在 wrap 里面添加 ul 列表,在列表中添加主要內容的圖片和文字,并為之設置 CSS 效果。使用 overflow 屬性規定當內容溢出元素框時發生的事情。在這里可以使用 overflow:hidden ,它一般用在固定寬高的 div 里面,目的是隱藏溢出使內部元素高度即使超過父元素也能夠被隱藏;此外, overflow:hidden 另一個流行的用途是用在沒有寬高的 div 里,其目的是清除浮動。
<div id="wrap">
<ul>
<li style="background-image: url(img/ 手風琴 5.jpg);">
<div>
<p> 我的個人浪漫之旅 || 美麗之約 </p>
</div>
</li>
<li style="background-image: url(img/sfq1.jpg);">
<div>
<p> 我的個人浪漫之旅 || 美麗之約 </p>
</div>
</li>
<li style="background-image: url(img/sfq6.jpg);">
<div>
<p> 我的個人浪漫之旅 || 美麗之約 </p>
</div>
</li>
<li style="background-image: url(img/sfq2.jpg); width: 789px;">
<div>
<p> 我的個人浪漫之旅 || 美麗之約 </p>
</div>
</li>
</ul>
</div>
#wrap{
width: 1090px;
height: 429px;
margin: 150px auto;
overflow: hidden;// 保障圖片在隨鼠標移動時不會發生錯位
}
#wrap ul{
width: 120%;
}
#wrap ul li{
list-style: none;
width: 100px;
height: 429px;
float: left;
}
#wrap ul li .txt{
width: 100px;
height: 429px;
background: rgba(0,0,0,0.5);
overflow: hidden;
}
#wrap ul li p{
padding: 0.5px 42px;
background: rgba(0,0,0,0.5);
color: white;
font-family: " 楷體 ";
font-size: 14px;
}
為了使圖片和文字在同一水平面上,用 float 屬性來清除浮動,并且用 rgba 屬性來為文字改變顏色和透明度。 rgba 是代表 Red (紅色) Green (綠色) Blue (藍色)和 Alpha (不透明度)三個單詞的縮寫,顏色值取 0 至 250 ;透明度取值在 0 倒忙1 之間,數值越小則越透明。
( 3 )引入 jquery 文件,并添加 js 效果。
<script src="shoufq.js" type="text/javascript" charset="utf-8"></script>
<script src="jquery-1.12.1.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
$('@wrap ul li').hover(function(){
$(this).stop().animate({
width : '789px'
},500).siblings().stop().animate({
width : '100px'
},500);
});
</script>
添加的 js 代碼中, $('@wrap ul li').hover 表示鼠標移上圖片時,被選中的圖片寬度變為 789px ,用時 500 毫秒。其他的圖片則用 siblings 來表示,它們的寬度在鼠標以上時變為 100px ,用時也是 500 毫秒。
效果圖:
如果這篇文章對你有幫助,你現在也想學習前端開發技術的話,可以關注私信我免費領取前端學習資料,觀看直播課噢!(私信方法:點擊我頭像進我主頁右上面有個私信按鈕)
篇會深化View拖拽實例,利用Flutter Animation、插值器以及AnimatedBuilder教大家實現帶動畫的抽屜效果。先來看效果:
通過構思,我們可以設想到實現抽屜的方式就是用Stack控件將兩個Widget疊加顯示,用GestureDetector監聽手勢滑動,動態移動頂層的Widget,當監聽到手勢結束的時候根據手勢滑動的距離動態將頂部Widget利用動畫效果滑動到結束位置即可。
實現底部Widget
class DownDrawerWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Container(child: Center(child: Text("底部Widget",),),); } }
這個Widget太簡單了,就不細說了。
實現頂部Widget
class UpDrawerWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Container(child: Center(child: Text("頂部Widget",),),); } }
實現方式和底部是一樣的。
實現可以移動的容器
上面兩個Widget都是單純用來顯示的Widget,因此繼承了StatelessWidget。接下來我們需要根據手勢動態移動頂部的Widget,因此需要繼承StatefulWidget。
// 頂部Widget class HomePageWidget extends StatefulWidget { @override State<StatefulWidget> createState()=> HomePageState(); } class HomePageState extends State<HomePageWidget> with SingleTickerProviderStateMixin { @override void initState() {...} @override void dispose() {...} @override Widget build(BuildContext context) {...} void _onViewDragDown(DragDownDetails callback) {...} void _onViewDrag(DragUpdateDetails callback) {...} void _onViewDragUp(DragEndDetails callback) {...} }
初始化狀態initState()
這個方法是在Widget初始化的時候系統的回調函數,我們需要在該函數中初始化動畫
AnimationController controller; @override void initState() { // 初始化動畫控制器,這里限定動畫時常為200毫秒 controller=new AnimationController(vsync: this, duration: const Duration(milliseconds: 200)); // vsync對象會綁定動畫的定時器到一個可視的widget,所以當widget不顯示時,動畫定時器將會暫停,當widget再次顯示時,動畫定時器重新恢復執行,這樣就可以避免動畫相關UI不在當前屏幕時消耗資源。 // 當使用vsync: this的時候,State對象必須with SingleTickerProviderStateMixin或TickerProviderStateMixin;TickerProviderStateMixin適用于多AnimationController的情況。 // 設置動畫曲線,就是動畫插值器 // 通過這個鏈接可以了解更多差值器,https://docs.flutter.io/flutter/animation/Curves-class.html,我們這里使用帶回彈效果的bounceOut。 CurvedAnimation curve=new CurvedAnimation(parent: controller, curve: Curves.bounceOut); // 增加動畫監聽,當手勢結束的時候通過動態計算到達目標位置的距離實現動畫效果。curve.value為當前動畫的值,取值范圍0~1。 curve.addListener(() { double animValue=curve.value; double offset=dragUpDownX - dragDownX; double toPosition; // 右滑 if (offset > 0) { if (offset > maxDragX / 5) { // 打開 toPosition=maxDragX; isOpenState=true; } else { if (isOpenState) { toPosition=maxDragX; isOpenState=true; } else { toPosition=0.0; isOpenState=false; } } } else { if (offset < (-maxDragX / 2.0)) { // 關 toPosition=0.0; isOpenState=false; } else { if (isOpenState) { toPosition=maxDragX; isOpenState=true; } else { toPosition=0.0; isOpenState=false; } } } dragOffset=(toPosition - dragUpDownX) * animValue + dragUpDownX; // 刷新位置 setState(() {}); }); }
結束Widget dispose()
當Widget不可用將被回收的時候,系統會回調dispose()方法,我們在這里回收動畫。
@override void dispose() { controller.dispose(); }
記錄按下的位置
double dragDownX=0.0; void _onViewDragDown(DragDownDetails callback) { dragDownX=callback.globalPosition.dx; }
拖動的時候刷新View的位置
/** * 最大可拖動位置 */ final double maxDragX=230.0; double dragOffset=0.0; void _onViewDrag(DragUpdateDetails callback) { double tmpOffset=callback.globalPosition.dx - dragDownX; if (tmpOffset < 0) { tmpOffset +=maxDragX; } // 邊緣檢測 if (tmpOffset < 0) { tmpOffset=0.0; } else if (tmpOffset >=maxDragX) { tmpOffset=maxDragX; } // 刷新 if (dragOffset !=tmpOffset) { dragOffset=tmpOffset; setState(() {}); } }
離手的時候記錄位置并執行動畫
/** * 脫手時候的位置 */ double dragUpDownX=0.0; void _onViewDragUp(DragEndDetails callback) { dragUpDownX=dragOffset; // 執行動畫,每次都從第0幀開始執行 controller.forward(from: 0.0); }
支持移動的Widget
@override Widget build(BuildContext context) { return Transform.translate( offset: Offset(dragOffset, 0.0), child: Container( child: GestureDetector( onHorizontalDragDown: _onViewDragDown, onVerticalDragDown: _onViewDragDown, onHorizontalDragUpdate: _onViewDrag, onVerticalDragUpdate: _onViewDrag, onHorizontalDragEnd: _onViewDragUp, onVerticalDragEnd: _onViewDragUp, child: Container( child: new UpDrawerWidget(), ),),),);}
Flutter動畫
總結一下,想在Flutter中實現動畫,需要先創建一個AnimationController控制器;如果有特殊的插值要求,再創建一個插值器,調用controller.forward()方法執行動畫,通過addListener()的回調改變對應數值之后調用setState(() {})方法刷新位置即可。
Flutter API還提供AnimatedBuilder用來簡化實現動畫的復雜性,讓我們不用手動調用addListener()方法。
信公眾號:Dotnet9,網站:Dotnet9,問題或建議:請網站留言, 如果對您有所幫助:歡迎贊賞。
閱讀導航
使用簡單動畫實現抽屜式菜單
使用 .NET CORE 3.1 創建名為 “AnimatedColorfulMenu” 的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.Light.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.Indigo.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
文件【MainWindow.xaml】,代碼不多,主要看左側菜單,啟動時,菜單在顯示窗體左側-150位置;點擊展開菜單,使用簡單的動畫,慢慢呈現在顯示窗體左側,源碼如下:
<Window x:Class="AnimatedColorfulMenu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d" Height="600" Width="1080" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen" WindowStyle="None">
<Window.Resources>
<Storyboard x:Key="CloseMenu">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="GridMenu">
<EasingDoubleKeyFrame KeyTime="0" Value="150"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="GridBackground">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OpenMenu">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="GridMenu">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="150"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="GridBackground">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="ButtonClose">
<BeginStoryboard x:Name="CloseMenu_BeginStoryboard" Storyboard="{StaticResource CloseMenu}"/>
</EventTrigger>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="ButtonOpen">
<BeginStoryboard Storyboard="{StaticResource OpenMenu}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Grid x:Name="GridBackground" Background="#55313131" Opacity="0"/>
<Button x:Name="ButtonOpen" HorizontalAlignment="Left" VerticalAlignment="Top" Background="{x:Null}" BorderBrush="{x:Null}" Width="30" Height="30" Padding="0">
<materialDesign:PackIcon Kind="Menu" Foreground="#FF313131"/>
</Button>
<!--左側抽屜菜單,默認在顯示窗體之外,點擊菜單圖標再通過簡單的動畫呈現出來-->
<Grid x:Name="GridMenu" Width="150" HorizontalAlignment="Left" Margin="-150 0 0 0" Background="White" RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Grid.RenderTransform>
<StackPanel>
<Image Height="140" Source="https://img.dotnet9.com/logo-foot.png" Stretch="Fill"/>
<ListView Foreground="#FF313131" FontFamily="Champagne & Limousines" FontSize="18">
<ListViewItem Height="45" Padding="0">
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="Recycle" Width="20" Height="20" Foreground="Gray" Margin="5" VerticalAlignment="Center"/>
<TextBlock Text="回收" Margin="10"/>
</StackPanel>
</ListViewItem>
<ListViewItem Height="45" Padding="0">
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="HelpCircleOutline" Width="20" Height="20" Foreground="#FFF08033" Margin="5" VerticalAlignment="Center"/>
<TextBlock Text="幫助" Margin="10"/>
</StackPanel>
</ListViewItem>
<ListViewItem Height="45" Padding="0">
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="Lightbulb" Width="20" Height="20" Foreground="Green" Margin="5" VerticalAlignment="Center"/>
<TextBlock Text="發送反饋" Margin="10"/>
</StackPanel>
</ListViewItem>
<ListViewItem Height="45" Padding="0">
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="Heart" Width="20" Height="20" Foreground="#FFD41515" Margin="5" VerticalAlignment="Center"/>
<TextBlock Text="推薦" Margin="10"/>
</StackPanel>
</ListViewItem>
<ListViewItem Height="45" Padding="0">
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="StarCircle" Width="20" Height="20" Foreground="#FFE6A701" Margin="5" VerticalAlignment="Center"/>
<TextBlock Text="溢價認購" Margin="10"/>
</StackPanel>
</ListViewItem>
<ListViewItem Height="45" Padding="0">
<StackPanel Orientation="Horizontal" Margin="10 0">
<materialDesign:PackIcon Kind="Settings" Width="20" Height="20" Foreground="#FF0069C1" Margin="5" VerticalAlignment="Center"/>
<TextBlock Text="設置" Margin="10"/>
</StackPanel>
</ListViewItem>
</ListView>
</StackPanel>
<Button x:Name="ButtonClose" HorizontalAlignment="Right" VerticalAlignment="Top" Background="{x:Null}" Foreground="#CCC" BorderBrush="{x:Null}" Width="30" Height="30" Padding="0">
<materialDesign:PackIcon Kind="Close"/>
</Button>
</Grid>
</Grid>
</Window>
效果圖實現代碼在文中已經全部給出,可直接Copy,按解決方案目錄組織代碼文件即可運行。
除非注明,文章均由 Dotnet9 整理發布,歡迎轉載。
轉載請注明本文地址:https://dotnet9.com/7397.html
歡迎掃描下方二維碼關注 Dotnet9 的微信公眾號,本站會及時推送最新技術文章
時間如流水,只能流去不流回!
點擊《【閱讀原文】》,本站還有更多技術類文章等著您哦!!!
此刻順便為我點個《【再看】》可好?
*請認真填寫需求信息,我們會在24小時內與您取得聯系。