者:mjn/Anitama 封面來源:GAINAX
layout是分鏡到原畫的過渡環節,分鏡大多數很小很草沒有細節,在layout步驟決定一個鏡頭中所有細節和背景,也關系到人物動作。
如何設計layout是老大難的問題,很多人問,于是這次平松禎史專門在博客寫了一篇文章來講解layout,作為一個超老手原畫的意見,本文無論對于業內還是愛好者,都非常有學習參考的價值。
需要注意的一點是,當下國產動畫很多時候都忽視layout的作用,分鏡干了layout的工作,原畫只管人物動作,這樣不但動作本身銜接性不好,而且整體透視感空間感非常差。
下文是文章的節選翻譯。
原文地址:http://ameblo.jp/tadashi-hiramatz/entry-12110925284.html
gainax《飛躍巔峰》的分鏡、layout、原畫、成片的實例
入江泰浩在推特上公開的《請問要來點兔子》第二季11集的layout
問的最多的問題是“如何畫layout”,其實并不是那么難的問題。
只是因為所包含的要素太多,不同作品不同場合下,意義會有所不同,原畫也一樣,一般論無法充分解釋,解釋了還可能產生誤解。所以,我覺得新人原畫還是在了解基本知識的基礎上,進行實戰學習比較好。(譯者注:本來layout的意思僅僅是構圖,但是現在很多情況下layout繪制者同時需要完成草原畫,即第一原畫,所以第一原畫和構圖統稱為layout的情況較多。)
動畫制作的作業工程每一個環節都有它的目的,不確切明白相關環節的意義,做出來的東西會讓觀眾看不懂,有些必要的東西無法正確傳達給觀眾,進而導致作品的失敗。
所以明白畫面構成、layout是什么、為什么,這點是必須的。
雖然無法用一般論說明清楚,我還是試試看吧,雖然可能會含有個人的主觀想法。
layout是分鏡之后的工程,下面的基礎都是分鏡合適的情況,要是分鏡有問題那怎么辦?那就是另外的問題了。
(譯者注,國內對于分鏡這個詞也有歧義,在某些國內動畫公司里,分鏡等同于layout,片尾職位表中的分鏡實際干了畫面構成layout的活,原畫則是單純做人物動作的繪制,不同于日式制作流程,日式流程中原畫負責layout,整個畫面的掌握權都在原畫手上。這也是比較科學合理的分配。)
layout是構成故事的影像制作的第一步,也是從演出到原畫的渡橋。
演出負責把腳本做成分鏡,把文字做成可以影像化的一卡一卡連續小設計圖,正確理解讀取腳本是前提。(譯者注:雖然在片尾我們經??吹窖莩龊头昼R(絵コンテ)是分開寫的,但是在動畫制作早期,分鏡和演出不分開,單記演出名,并不設分鏡職位,做了分鏡的人理所當然負責這集的演出工作,所以這里分鏡和演出統稱為演出,和anitama談論的演出、演出tag是一個意思。現在因為種種原因演出和分鏡經常是分開的,但是考慮到分鏡演出對整體作業的影響我們還是統稱為演出。)
對于原畫則是以正確理解分鏡、讀取演出意圖為前提,才能畫layout。
5W1H——“什么時候?在哪里?誰?在做什么?為了什么?怎么做?”是必須基本明確的,總結成簡要三點則是:地點、時間、氣氛。
把這三點明確恰當得表現出來就是layout的目的。所以說,要畫某一鏡頭之前,不明白這個場景和發生在這個場景的故事是畫不了的,最起碼不明白前后鏡頭的關系是不能畫的。
簡單說明這三要素。
- 地點——也就是舞臺。在哪個地方。這個地方有什么。天氣怎么樣。
- 時間——上午下午黃昏夜晚,具體是哪個時間帶。時間是如何變化的。
- 氣氛——人物是什么樣的心情、目的、動作。即使是人物不出現的的鏡頭也能包含氣氛。
分鏡并不需要把上述要素表現得太清楚,layout本身就需要原畫讀取理解分鏡之后收集影像中的必要要素。雖然寫的是演出到原畫的渡橋,其實是把之后的所有作業工程都交渡過去了。
演出(分鏡)上的三要素是“畫面大小、被拍人物的角度、視野角”,三者本身之間密切相關、相互影響。
為什么是特寫?為什么用仰視的鏡頭?為什么用望遠構圖?等等之類的都應該有其演出意圖。
過于追求細節估計說不完說不盡,這次就概括成“地點、時間、氣氛”。
最重要的是氣氛。地點、時間、動作都應該為氣氛的表現服務。氣氛、人物的感覺不變化,人物的動作也不會產生。即使機械作畫也一樣有感覺和趨勢存在。
演出方面,氣氛、感覺不變化,鏡頭也不變化。雖然不同演出家的鏡頭使用方法有差別,但是多數都是基于固定鏡頭(FIX),要使鏡頭發生變化必須有讓其產生變化的必要性存在。人物的動作也同理。
分鏡畫得無論多細致還是多草多簡單,都應該能讓工程后面的制作人員能明白這個作品想要表現什么、這個場景事件有什么意圖、鏡頭需要表現出怎樣的演出效果、登場人物的心情感受等等。場景不同,可能分鏡三要素的優先順序有不同。會話場景和打斗場景必要的要素肯定有不同,不同鏡頭之間也可能有不同。
本文僅供Anitama發表,任何單位或個人,不得以任何形式刊載本文的部分或全部內容。
官方網站:http://www.anitama.cn
官方微博:@AnimeTamashii
微信公眾號:AniTama
合作郵箱:bd@anitama.cn
原文: m.anitama.cn/article/1a3d15c14218472a?utm_source=toutiao
過本文章,你可以掌握以下內容:
1、Pyside6 Layout介紹
QtWidgets.QLayout是Qt中用于管理窗口或對話框中小部件(控件)布局的基類。它是一個抽象基類,定義了所有布局類共有的接口和行為。QLayout及其子類的主要作用是自動管理小部件的位置和大小,以便于創建整潔和靈活的圖形用戶界面(GUI),對于復雜界面布局是很重要的,主要作用包括:
Layout繼承關系圖
2、Pyside6 Layout布局解釋及示例
以下是繼承自QtWidgets.QLayout的布局,每種布局有對應的行為。
布局 | 行為 | 對應html |
QHBoxLayout | 線性水平布局 | 類似于display: flex; flex-direction: row;的Flexbox布局 |
QVBoxLayout | 線性垂直布局 | 類似于display: flex; flex-direction: column;的Flexbox布局 |
QGridLayout | 在可轉位網格 XxY 中 | 類似于html的table行和列 |
QStackedLayout | 堆疊 (z) 于彼此前面 | 類似于css的z-index,并控制隱藏顯示效果 |
QHBoxLayout是Qt中的一個布局管理器類,用于按水平方向排列小部件。它繼承自QLayout,提供了一種簡便的方式來自動管理窗口或對話框中小部件的位置和大小。使用QHBoxLayout,可以將小部件從左到右依次排列,而不需要手動指定每個小部件的具體位置。
QHBoxLayout繼承關系圖
簡單的示例如下:
import sys
from PySide6.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("QHBoxLayout之水平布局")
self.setMinimumSize(400,300)
layout=QHBoxLayout()
layout.addWidget(QPushButton("1"))
layout.addWidget(QPushButton("2"))
layout.addWidget(QPushButton("3"))
widget=QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
if __name__=='__main__':
app=QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec()
QHBoxLayout示例效果圖
QVBoxLayout是Qt中的一個布局管理器類,用于垂直方向排列小部件。它繼承自QLayout,提供了一種簡便的方式來自動管理窗口或對話框中小部件的位置和大小。使用QVBoxLayout,可以將小部件從上到下依次排列,而不需要手動指定每個小部件的具體位置。
QVBoxLayout繼承關系圖
簡單示例如下:
import sys
from PySide6.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("QVBoxLayout之垂直布局")
self.setMinimumSize(400, 300)
layout=QVBoxLayout()
layout.addWidget(QPushButton("1"))
layout.addWidget(QPushButton("2"))
layout.addWidget(QPushButton("3"))
widget=QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
if __name__=='__main__':
app=QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec()
效果圖如下:
QVBoxLayout示例效果圖
QGridLayout是Qt中一個非常強大的布局管理器,它提供一種網格式布局,這種布局由行和列組成(類似table),每個小部件占據網格中的一個或多個單元格。QGridLayout提供了靈活的方式來創建復雜的用戶界面,使得小部件的布局可以精確控制,同時也能自動適應窗口大小的變化,主要特性有:
QGridLayout繼承關系圖
示例代碼如下:
import sys
from PySide6.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("QGridLayout之網格布局")
self.setMinimumSize(400, 300)
layout=QGridLayout()
# 為窗口部件設置樣式表,添加邊框
self.setStyleSheet("QWidget { border: 2px solid black; }")
layout.addWidget(QLabel('第0行第0列'), 0, 0)
layout.addWidget(QLabel('第0行第1列'), 0, 1)
layout.addWidget(QLabel('第1行第0列'), 1, 0)
layout.addWidget(QLabel('第1行第1列'), 1, 1)
widget=QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
if __name__=='__main__':
app=QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec()
效果圖如下:
QGridLayout示例效果圖
QStackedLayout是Qt中的一個布局管理器,它可以在相同的空間內堆疊多個小部件,但一次只顯示一個小部件。這種布局非常適合用于實現向導、選項卡和其他需要在多個頁面之間切換的界面。
QStackedLayout繼承關系圖
主要特性:
常用方法技巧:indexOf()函數返回小部件在該列表中的索引??梢允褂胊ddWidget()函數添加小部件到列表末尾,或者使用insertWidget()函數在給定索引處插入。removeWidget()函數從布局中移除給定索引的小部件。可以使用count()函數獲取布局中包含的小部件數量。widget()函數返回給定索引位置的小部件。當前顯示在屏幕上的小部件的索引由currentIndex()給出,并且可以使用setCurrentIndex()進行更改。以類似的方式,可以使用currentWidget()函數檢索當前顯示的小部件,并使用setCurrentWidget()函數進行更改。每當布局中的當前小部件發生變化或從布局中移除小部件時,分別會發出currentChanged()和widgetRemoved()信號。
示例代碼如下:
import sys
from PySide6.QtGui import QPalette, QColor
from PySide6.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("QStackedLayout之堆疊布局")
self.setMinimumSize(400, 300)
pagelayout=QVBoxLayout()
button_layout=QHBoxLayout()
self.stacklayout=QStackedLayout()
pagelayout.addLayout(button_layout)
pagelayout.addLayout(self.stacklayout)
btn=QPushButton("red")
btn.pressed.connect(self.activate_tab_1)
button_layout.addWidget(btn)
self.stacklayout.addWidget(Color("red"))
btn=QPushButton("green")
btn.pressed.connect(self.activate_tab_2)
button_layout.addWidget(btn)
self.stacklayout.addWidget(Color("green"))
btn=QPushButton("yellow")
btn.pressed.connect(self.activate_tab_3)
button_layout.addWidget(btn)
self.stacklayout.addWidget(Color("yellow"))
widget=QWidget()
widget.setLayout(pagelayout)
self.setCentralWidget(widget)
def activate_tab_1(self):
self.stacklayout.setCurrentIndex(0)
def activate_tab_2(self):
self.stacklayout.setCurrentIndex(1)
def activate_tab_3(self):
self.stacklayout.setCurrentIndex(2)
class Color(QWidget):
def __init__(self, color):
super(Color, self).__init__()
self.setAutoFillBackground(True)
palette=self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
if __name__=='__main__':
app=QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec()
效果圖如下:
QStackedLayout示例效果圖
使用QHBoxLayout、QVBoxLayout、QGridLayout、QStackedLayout這幾種布局組合使用,來控制界面的整體風格視角,制作精美的布局效果
示例代碼如下:
import sys
from PySide6.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("混合布局")
self.setMinimumSize(400, 300)
self.setStyleSheet("QLabel { border: 1px solid blue; }")
layout1=QHBoxLayout()
layout2=QVBoxLayout()
layout3=QVBoxLayout()
layout1.setContentsMargins(0,0,0,0)
layout1.setSpacing(20)
layout2.addWidget(QLabel('hbox1-QVBoxLayout1'))
layout2.addWidget(QLabel('hbox1-QVBoxLayout2'))
layout2.addWidget(QLabel('hbox1-QVBoxLayout3'))
layout1.addLayout(layout2)
layout1.addWidget(QLabel('hbox2'))
layout3.addWidget(QLabel('hbox2-QVBoxLayout1'))
layout3.addWidget(QLabel('hbox2-QVBoxLayout2'))
layout1.addLayout(layout3)
widget=QWidget()
widget.setLayout(layout1)
self.setCentralWidget(widget)
if __name__=='__main__':
app=QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec()
效果圖如下:
混合布局效果圖
注意:QLayout邊框及樣式不能通過這種方式來設置樣式效果,需要指定Widget的樣式
#無效果
self.setStyleSheet("QHBoxLayout { border: 1px solid black; }")
#有效果
self.setStyleSheet("QLabel { border: 1px solid blue; }")
由于QHBoxLayout、QVBoxLayout、QGridLayout、QStackedLayout布局放置的控件,不增加任何處理,生成的控件會固定住窗口大小,可以通過下面來動態排列控件。
示例代碼如下:
import sys
from PySide6.QtCore import QRect, QSize, QPoint, Qt
from PySide6.QtWidgets import *
class FlowLayout(QLayout):
def __init__(self, parent=None, margin=0, spacing=-1):
super(FlowLayout, self).__init__(parent)
if parent is not None:
self.setContentsMargins(margin, margin, margin, margin)
self.setSpacing(spacing)
self.items=[]
def addItem(self, item):
self.items.append(item)
def count(self):
return len(self.items)
def itemAt(self, index):
if index >=0 and index < len(self.items):
return self.items[index]
return None
def takeAt(self, index):
if index >=0 and index < len(self.items):
return self.items.pop(index)
return None
def expandingDirections(self):
return 0
def hasHeightForWidth(self):
return True
def heightForWidth(self, width):
height=self.doLayout(QRect(0, 0, width, 0), True)
return height
def setGeometry(self, rect):
super(FlowLayout, self).setGeometry(rect)
self.doLayout(rect, False)
def sizeHint(self):
return QSize(self.doLayout(QRect(0, 0, 10000, 0), True), 10000)
def doLayout(self, rect, testOnly):
x=rect.x()
y=rect.y()
lineHeight=0
for item in self.items:
wid=item.widget()
spaceX=self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton,Qt.Horizontal)
spaceY=self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton,Qt.Vertical)
nextX=x + item.sizeHint().width() + spaceX
if nextX - spaceX > rect.right() and lineHeight > 0:
x=rect.x()
y=y + lineHeight + spaceY
nextX=x + item.sizeHint().width() + spaceX
lineHeight=0
if not testOnly:
item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
x=nextX
lineHeight=max(lineHeight, item.sizeHint().height())
return y + lineHeight - rect.y()
if __name__=='__main__':
app=QApplication(sys.argv)
mainWidget=QWidget()
mainWidget.setMinimumSize(300, 200)
layout=FlowLayout(mainWidget)
for i in range(50):
layout.addWidget(QPushButton(f'Button {i}'))
mainWidget.setLayout(layout)
mainWidget.show()
sys.exit(app.exec_())
效果如下:
自定義Layout效果圖
在程序員開發軟件界面系統也都是有多種多樣,每種開發語言基本上都有一種或多種界面引擎如:C skin, Direct UI , 還有金山、迅雷等廠商的界面SDK。
今天推薦一個輕量級、自由度高、使用方便的界面庫 Htmlayout/Sciter。HTMLayout是一個免費的開源界面庫(核心未開源),以DLL的方式運行,并提供一個API的調用接口和一系列的C++封裝和sample例程。HTMLayout: 快速,輕量、嵌入式的,基于HTML/CSS渲染技術和布局管理的界面引擎組件,可以高效地解析和渲染HTML網頁。其幾乎支持所有的HTML元素和CSS3標準,并根據界面庫的特征,做了很多有用的功能性擴展。
界面預覽
這里著重地說一下在 aardio 軟件中的使用,作者把 HTMLayout和 Sciter 制作成了擴展庫, 并且免費開源, 通過這個擴展庫你知道會一點點 HTML 和 CSS 知識就可以方便地制作各種漂亮的 ui。通過作者的努力你還可以直接在界面上使用現在最流行的字體圖標,還使擴展庫支持了模板功能,你可以像寫PHP一樣寫桌面軟件的界面HTML,雖然看起來簡單的代碼,但用起來會非常方便。
效果圖
效果圖
言歸正傳, 我們用aardio一步步來制作一個最簡單的界面。
1、打開軟件》新建工程》選擇web界面》選擇HTMLayout》創建工程
字體圖標
效果圖
aardio 里查看 main.aardio 源碼
import win.ui;
/*DSG{{*/
var winform=win.form(text="htmlayout";right=761;bottom=609;border="none")
winform.add()
/*}}*/
import web.layout;
import web.layout.behavior.windowCommand;
import web.layout.behavior.tabs;
// 加載網頁
var wbLayout=web.layout( winform );
wbLayout.go("\layout\ui.html");
if(_STUDIO_INVOKED){
import web.layout.debug;
wbLayout.attachEventHandler( web.layout.debug );
}
//添加陰影邊框
import win.ui.shadow;
win.ui.shadow( winform,50,3 );
winform.show()
win.loopMessage();
從上面我們可以看出,軟件的主要界面是由 ui.html,ui.css,tabs.css 這幾個文件組成的。然后你可以根據自己軟件界面的需要進行調整。
工程項目
以下是我自己這二天搭建的一個軟件的界面,就是一個簡單的軟件基本框架。
演示圖上
工程項目目錄結構
如果你對htmlayout感興趣,可以查看 https://bbs.aardio.com/forum.php?mod=forumdisplay&fid=128&page=1 了解更多更詳細的教程。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。