using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace HistoryDLL
{
///
/// HomePage.xaml 的互動邏輯
///
public partial class HomePage : UserControl
{
public event EventHandler OnLoadProgessComplete;
DispatcherTimer dt = new DispatcherTimer();
Storyboard progressWidthStoryBoard = new Storyboard();
Storyboard progressHeightStoryBoard = new Storyboard();
DoubleAnimation dbOffsetWidth;
DoubleAnimation dbOffsetHeight;
//亂數飛入
private Random rnd = new Random(Guid.NewGuid().GetHashCode());
//Block size
private int blockWidth = 0;
private int blockHeight = 0;
private int nonesize = 0;
//事件數量
private int eventTotalCount = 0;
//載入完成數量
private int eventLoadCount = 0;
//歷史牆控制項
private Grid HistoryWallControl = new Grid();
//區塊大小設定
private static int cutForTwowidth = 289;
private static int cutForTwoheight = 224;
private static int cutForSixwidth = 209;
private static int cutForSixheight = 157;
//紀錄顯示畫面的年份
public List xmlDataList = new List();
public List borderlist = new List();
public List myborderList = new List();
public int StoryBoardTime = 200;
public int DelayTimeRate = 100;
public int HistoryWallTime = 600;
SolidColorBrush sb = new SolidColorBrush(ConfigSettingClass.TimelineCollect.BackgroundColor);
private SolidColorBrush TextBlockExtendColor = new SolidColorBrush(ConfigSettingClass.TimelineCollect.TextColor);
public HomePage(int width, int height)
{
InitializeComponent();
this.uxLoadBar.Width = width;
this.uxLoadBar.Height = height;
if (GlobalFunction.isSolutionUsing4K)
{
cutForTwowidth *= 2;
cutForTwoheight *= 2;
cutForSixwidth *= 2;
cutForSixheight *= 2;
uxProgressBar.Height *= 2;
uxProgressBar.Margin = new Thickness(0, uxProgressBar.Margin.Top * 2, 0, 0);
}
SetStoryboardMotionX();
SetStoryboardMotionY();
uxProgressBar.Background = sb;
uxLoadingProgress.LoadingCompleted += new EventHandler(uxLoadingProgress_LoadingCompleted);
uxLoadingProgress.Start();
uxLoadingProgress.Minimum = 0;
uxLoadingProgress.Maximum = 100;
}
private void uxLoadingProgress_LoadingCompleted(object sender, EventArgs e)
{
progressWidthStoryBoard.Stop();
dbOffsetWidth.From = this.uxProgressBar.Width;
dbOffsetWidth.To = (eventLoadCount * this.uxLoadBar.Width) / eventTotalCount;
progressWidthStoryBoard.Begin();
uxLoadingProgress.Visibility = System.Windows.Visibility.Collapsed;
CloseLoadingMap();
OnLoadProgessComplete?.Invoke(this,null);
}
private void CloseLoadingMap()
{
for (int i = 0; i < 60; i++)
{
Path path = new Path();
path = FindName("m" + string.Format("{0:D2}", i)) as Path;
path.Visibility = System.Windows.Visibility.Collapsed;
}
Grid gd = new Grid();
gd = FindName("m60") as Grid;
gd.Visibility = System.Windows.Visibility.Collapsed;
}
public void SetBlockCommonSetting(int width, int height, int nousesize)
{
blockWidth = width;
blockHeight = height;
nonesize = nousesize;
if (GlobalFunction.isSolutionUsing4K)
{
//blockWidth *= 2;
//blockHeight *= 2;
//nonesize *= 2;
}
}
private void HistoryWallStart()
{
dt.Interval = TimeSpan.FromMilliseconds(HistoryWallTime);
dt.Tick += new EventHandler(dt_Tick);
dt.Start();
}
void dt_Tick(object sender, EventArgs e)
{
dt.Stop();
//將歷史牆提到最上層
Canvas.SetZIndex(HistoryWallControl, 1);
OpacityFadeInAndOut();
}
//設定時間讓歷史牆的Opacity漸改變
private void OpacityFadeInAndOut()
{
Storyboard historywallshow = new Storyboard();
DoubleAnimation dbOffset = new DoubleAnimation()
{
Duration = TimeSpan.FromMilliseconds(200),
EasingFunction = new ExponentialEase()
{
EasingMode = EasingMode.EaseIn,
Exponent = 3,
},
From = 0,
To = 1
};
Storyboard.SetTarget(dbOffset, HistoryWallControl);
Storyboard.SetTargetProperty(dbOffset, new PropertyPath(Grid.OpacityProperty));
historywallshow.Completed += new EventHandler(historywallshow_Completed);
historywallshow.Children.Add(dbOffset);
historywallshow.FillBehavior = FillBehavior.HoldEnd;
historywallshow.Begin();
}
void historywallshow_Completed(object sender, EventArgs e)
{
HistoryWallControl.Opacity = 1;
//結束後~將歷史牆降到最下層~不然點擊會點不到
Canvas.SetZIndex(HistoryWallControl, 0);
uxLoadBar.Opacity = 0;
ReleaseAllSetting();
}
//釋放所有資源
private void ReleaseAllSetting()
{
xmlDataList = new List();
borderlist = new List();
myborderList = new List();
progressWidthStoryBoard = new Storyboard();
progressHeightStoryBoard = new Storyboard();
uxLoadBar.Visibility = System.Windows.Visibility.Collapsed;
}
//將每個年分區塊顯示出來~並且播放飛入的動畫
private void ShowBlock()
{
uxProgressBar.Opacity = 0;
uxGradientStop.Offset = 1;
for (int i = 0; i < borderlist.Count; i++)
{
uxLoadBar.Children.Add(borderlist[i]);
}
this.Refresh();
for (int i = 0; i < myborderList.Count; i++)
{
uxLoadBar.Children.Add(myborderList[i]);
myborderList[i].FlyAnimationStart();
this.Refresh();
}
}
///
/// 設定每個Block的位置
///
private void SetBlockPos()
{
int marginbtm = 250;
if (GlobalFunction.isSolutionUsing4K)
marginbtm *= 2;
//設定每個年分區塊的位置
for (int count = 0; count < borderlist.Count; count++)
{
//先設定第一個
if (count == 0)
{
borderlist[count].Margin = new Thickness(-nonesize, 0, 0, marginbtm);
continue;
}
borderlist[count].Margin = new Thickness(borderlist[count - 1].Margin.Left + blockWidth, 0, 0, marginbtm);
}
}
///
/// 根據事件的數量~新建出Image並設定其動畫
///
private void SetEventAnimation()
{
int eventcount = xmlDataList.Count;
for (int index = 0; index < eventcount; index++)
{
//如果該年只有兩個事件~的動畫位置
if (xmlDataList[index].monthclassList.Count <= 2)
{
for (int i = 0; i < xmlDataList[index].monthclassList.Count; i++)
{
int randonvalue = rnd.Next(0, 401);
if (i == 0)
{
int fitValue = 92;
if (GlobalFunction.isSolutionUsing4K)
fitValue *= 2;
//區塊寬度, 區塊高度, 該區塊的起始位置 (左 + 底), 該區塊飛入後的終點位置 (左 + 底) + 動畫時間, 動畫的延遲時間
//91 : 77 (年份寬度) + "上下"區塊間的Thickness寬度 10 + 切割該區塊的係數 4
MyBorder newimage = new MyBorder(cutForTwowidth, cutForTwoheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - cutForTwowidth) / 2, borderlist[index].Margin.Bottom + fitValue, StoryBoardTime, randonvalue);
myborderList.Add(newimage);
}
else
{
int fitValue = 103;
if (GlobalFunction.isSolutionUsing4K)
fitValue *= 2;
//97 : 77 (年份寬度) + "上下"區塊間的Thickness寬度 10 + 切割下區塊的係數 (上下) 4 + 往上多飛一個Thickness寬度 5 + 切割該區塊的係數(下) 2
MyBorder newimage = new MyBorder(cutForTwowidth, cutForTwoheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - cutForTwowidth) / 2, borderlist[index].Margin.Bottom + fitValue + (i * cutForTwoheight), StoryBoardTime, randonvalue);
myborderList.Add(newimage);
}
}
}
//如果該年超過兩個事件~則動畫位置
else
{
for (int i = 0; i < xmlDataList[index].monthclassList.Count; i++)
{
int randonvalue = rnd.Next(0, 401);
if (i > 5)
{
break;
}
//排(橫)
int Row = i / 2;
//列(直)
int colu = i % 2;
int thicknessValue = 5;
int fitXvalue = 210;
int fitYvalue = 91;
if (GlobalFunction.isSolutionUsing4K)
{
thicknessValue *= 2;
fitXvalue *= 2;
fitYvalue *= 2;
}
if (Row == 0)
{
if (colu == 0)
{
MyBorder newimage = new MyBorder(cutForSixwidth, cutForSixheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - ((fitXvalue + thicknessValue) * 2)) / 2, borderlist[index].Margin.Bottom + fitYvalue, StoryBoardTime, randonvalue);
myborderList.Add(newimage);
}
else
{
//225 : cutForSixwidth 210 + 該區塊的"左右"的Thickness 10 + 右邊區塊的"左"Thickness 5
MyBorder newimage = new MyBorder(cutForSixwidth, cutForSixheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - ((fitXvalue + thicknessValue) * 2)) / 2 + ((fitXvalue + thicknessValue * 2)), borderlist[index].Margin.Bottom + fitYvalue, StoryBoardTime, randonvalue);
myborderList.Add(newimage);
}
}
else
{
if (colu == 0)
{
//14 : 區塊"上下"的Thickness 10 + 切割該區塊的係數 4
MyBorder newimage = new MyBorder(cutForSixwidth, cutForSixheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - ((fitXvalue + thicknessValue) * 2)) / 2, borderlist[index].Margin.Bottom + fitYvalue + (Row * cutForSixheight) + (11 * Row), StoryBoardTime, randonvalue);
myborderList.Add(newimage);
}
else
{
//225 : cutForSixwidth 210 + 該區塊的"左右"的Thickness 10 + 右邊區塊的"左"Thickness 5
MyBorder newimage = new MyBorder(cutForSixwidth, cutForSixheight, borderlist[index].Margin.Left, borderlist[index].Margin.Bottom, borderlist[index].Margin.Left + (blockWidth - ((fitXvalue + thicknessValue) * 2)) / 2 + (fitXvalue + thicknessValue * 2), borderlist[index].Margin.Bottom + fitYvalue + (Row * cutForSixheight) + (11 * Row), StoryBoardTime, randonvalue);
myborderList.Add(newimage);
}
}
}
}
}
}
#region X 與 Y 軸動畫
private void SetStoryboardMotionX()
{
progressWidthStoryBoard = new Storyboard();
dbOffsetWidth = new DoubleAnimation()
{
Duration = TimeSpan.FromMilliseconds(1000),
EasingFunction = new ExponentialEase()
{
EasingMode = EasingMode.EaseIn,
Exponent = 0.3
},
};
Storyboard.SetTarget(dbOffsetWidth, this.uxProgressBar);
Storyboard.SetTargetProperty(dbOffsetWidth, new PropertyPath(Grid.WidthProperty));
progressWidthStoryBoard.Children.Add(dbOffsetWidth);
progressWidthStoryBoard.Completed += new EventHandler(progressStoryBoard_Completed);
progressWidthStoryBoard.FillBehavior = FillBehavior.HoldEnd;
}
void progressStoryBoard_Completed(object sender, EventArgs e)
{
progressHeightStoryBoard.Begin();
}
public void SetEventCount(int count)
{
eventTotalCount = count;
}
private void SetStoryboardMotionY()
{
progressHeightStoryBoard = new Storyboard();
int aniHeight = 77;
if (GlobalFunction.isSolutionUsing4K)
aniHeight *= 2;
dbOffsetHeight = new DoubleAnimation()
{
Duration = TimeSpan.FromMilliseconds(500),
EasingFunction = new ExponentialEase()
{
EasingMode = EasingMode.EaseIn,
Exponent = 0.3
},
From = this.uxProgressBar.Height,
To = aniHeight,
};
Storyboard.SetTarget(dbOffsetHeight, this.uxProgressBar);
Storyboard.SetTargetProperty(dbOffsetHeight, new PropertyPath(Grid.HeightProperty));
progressHeightStoryBoard.Children.Add(dbOffsetHeight);
progressHeightStoryBoard.Completed += new EventHandler(progressHeightStoryBoard_Completed);
progressHeightStoryBoard.FillBehavior = FillBehavior.HoldEnd;
}
void progressHeightStoryBoard_Completed(object sender, EventArgs e)
{
while (true)
{
if (xmlDataList.Count > 0)
{
for (int i = 0; i < xmlDataList.Count; i++)
{
Border bd = new Border();
TextBlock tb = new TextBlock();
tb.Foreground = TextBlockExtendColor;
tb.FontSize = GlobalFunction.isSolutionUsing4K ? 40 * 1.5 : 40;
tb.TextTrimming = TextTrimming.CharacterEllipsis;
tb.VerticalAlignment = System.Windows.VerticalAlignment.Center;
tb.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
string langStr = xmlDataList[i].yearlan1;
if (ConfigSettingClass.MainBackCollect.DefaultLangIndex == 1)
{
langStr = xmlDataList[i].yearlan2;
}
else if (ConfigSettingClass.MainBackCollect.DefaultLangIndex == 2)
{
langStr = xmlDataList[i].yearlan3;
}
else if (ConfigSettingClass.MainBackCollect.DefaultLangIndex == 3)
{
langStr = xmlDataList[i].yearlan4;
}
tb.Text = langStr;
bd.Child = tb;
bd.Width = blockWidth;
bd.Height = blockHeight;
bd.BorderThickness = new Thickness(5);
bd.BorderBrush = Brushes.Transparent;
bd.Background = sb;
bd.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
bd.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
borderlist.Add(bd);
}
break;
}
}
//在整個動畫結束後~代表資料已經載入完成此時才知道顯示在前面個年份是哪幾個~
//設定每個Block的位置
SetBlockPos();
//根據事件的數量~新建出Image並設定其動畫
SetEventAnimation();
//顯示區塊及動畫
ShowBlock();
//設定時間歷史牆啟動
HistoryWallStart();
}
#endregion
//觸發整個動畫起始位置
public void AddLoadCount()
{
eventLoadCount++;
RunProgressStoryboard();
}
private void RunProgressStoryboard()
{
uxLoadingProgress.EndValue = ((double)eventLoadCount / (double)eventTotalCount) * 100d;
}
internal void SetHistoryWallControl(Grid uxCyclicGrid)
{
HistoryWallControl = uxCyclicGrid;
}
}
/// 擴充uiElement類別的方法
/// 為uiElement類別增加element即時重整的功能
public static class uiElementExtension
{
private static Action NoDoDelegate = delegate () { };
public static void Refresh(this UIElement uiElement)
{
uiElement.Dispatcher.Invoke(DispatcherPriority.Render, NoDoDelegate);
}
public static void WebRefresh(this UIElement uiElement)
{
uiElement.Dispatcher.Invoke(DispatcherPriority.ContextIdle, NoDoDelegate);
}
}
//自訂義Image
public class MyBorder : Border
{
//區塊大小
public int borderwidth;
public int borderheight;
//動畫起始位置
public double beginPosX;
public double beginPosY;
//動畫結束位置
public double endPosX;
public double endPosY;
public Storyboard myborderStoryboard = new Storyboard();
//動畫運行時間
public int storyboardTime;
//動畫的Delay time 讓整個飛入的物件不會同時飛
public int storyboardBeginTime;
private SolidColorBrush RotateContainColor = new SolidColorBrush(ConfigSettingClass.EventCollect.BackgroundColor);
public MyBorder(int width, int height, double bPosX, double bPosY, double ePosX, double ePosY, int StoryboardTime, int STbeginTime)
{
borderwidth = width;
borderheight = height;
beginPosX = bPosX;
beginPosY = bPosY;
endPosX = ePosX;
endPosY = ePosY;
storyboardTime = StoryboardTime;
storyboardBeginTime = STbeginTime;
this.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
this.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
this.Background = RotateContainColor;
this.BorderThickness = new Thickness(0);
this.Opacity = 0;
SetTheFlyStoryboard();
}
public void FlyAnimationStart()
{
this.Opacity = 1;
myborderStoryboard.Begin();
}
//飛入的動畫
private void SetTheFlyStoryboard()
{
ThicknessAnimation dbOffset = new ThicknessAnimation()
{
Duration = TimeSpan.FromMilliseconds(storyboardTime),
EasingFunction = new CircleEase()
{
EasingMode = EasingMode.EaseOut,
},
From = new Thickness(beginPosX, 0, 0, beginPosY),
To = new Thickness(endPosX, 0, 0, endPosY)
};
DoubleAnimation dbOffsetWidth = new DoubleAnimation()
{
Duration = TimeSpan.FromMilliseconds(storyboardTime),
EasingFunction = new CircleEase()
{
EasingMode = EasingMode.EaseOut,
},
From = 0,
To = borderwidth
};
DoubleAnimation dbOffsetHeight = new DoubleAnimation()
{
Duration = TimeSpan.FromMilliseconds(storyboardTime),
EasingFunction = new CircleEase()
{
EasingMode = EasingMode.EaseOut,
},
From = 0,
To = borderheight
};
DoubleAnimation dbOffsetOpacity = new DoubleAnimation()
{
Duration = TimeSpan.FromMilliseconds(storyboardTime),
EasingFunction = new CircleEase()
{
EasingMode = EasingMode.EaseOut,
},
From = 0,
To = 1
};
Storyboard.SetTarget(dbOffset, this);
Storyboard.SetTarget(dbOffsetWidth, this);
Storyboard.SetTarget(dbOffsetHeight, this);
Storyboard.SetTarget(dbOffsetOpacity, this);
Storyboard.SetTargetProperty(dbOffset, new PropertyPath(Border.MarginProperty));
Storyboard.SetTargetProperty(dbOffsetWidth, new PropertyPath(Border.WidthProperty));
Storyboard.SetTargetProperty(dbOffsetHeight, new PropertyPath(Border.HeightProperty));
Storyboard.SetTargetProperty(dbOffsetOpacity, new PropertyPath(Border.OpacityProperty));
myborderStoryboard.BeginTime = TimeSpan.FromMilliseconds(storyboardBeginTime);
myborderStoryboard.Children.Add(dbOffset);
myborderStoryboard.Children.Add(dbOffsetWidth);
myborderStoryboard.Children.Add(dbOffsetHeight);
myborderStoryboard.Children.Add(dbOffsetOpacity);
myborderStoryboard.FillBehavior = FillBehavior.HoldEnd;
}
}
}