70+ composants Material/Cupertino · 30+ utilitaires · 6 managers système
SecureStorage · AnimationEngine · OfflineSync · Accessibility
Button, Input, Switch, Slider, Dialog, Modal, Tabs, List, Cards, Camera, QRCode, Map...
SecureStorage, AnimationEngine, FetchClient, DataStore, I18n, FormValidator, WebSocket...
ErrorHandler, MemoryManager, SecurityManager, AccessibilityManager, PerformanceMonitor
AES-GCM, IV aléatoire, cache mémoire, export/import chiffré
On ne va pas se mentir. Flutter est meilleur. Point.
Mais voici où on se situe vraiment, avec nos forces ET nos faiblesses.
L'écart est ÉNORME : 30% de performance en plus.
Ionic traîne le DOM, nous on dessine directement sur canvas.
Dans ces cas, on peut descendre à 92% quand React Native reste à 93-94%.
C'est rare, mais ça arrive. On assume.
Flutter est meilleur. On ne le rattrapera pas.
React Native nous talonne, et parfois nous dépasse.
Mais on écrase Ionic.
Et surtout, on fait tout ça en JavaScript pur, sans Dart, sans bridge, sans complexité inutile.
C'est notre vrai combat.
On ne bat pas Flutter en perf pure. Mais pour le reste...
| CanvasFramework | Flutter | React Native | Ionic | |
|---|---|---|---|---|
| Performance | 🔥 60 FPS | 🔥 60 FPS | 🔥 55 FPS | 🔥 30-40 FPS |
| Langage | ✅ JavaScript | ❌ Dart | ✅ JavaScript | ✅ JavaScript |
| Courbe apprentissage | ⭐ 1/10 | 🔥 8/10 | 🔥 5/10 | 🔥 3/10 |
| Bundle size | +/- 450 KB | 2MB+ | 5MB+ | 3MB+ |
| DOM | ❌ Non | ❌ Non | ✅ Oui (bridge) | ✅ Oui |
| Production médicale | ✅ Oui | ✅ Oui | ✅ Oui | ✅ Oui |
5 types Material, 5 types Cupertino, 3 formes, ripple, elevation
const btn = new Button(framework, {
text: 'Cliquez-moi',
type: 'filled',
shape: 'rounded',
onClick: () => console.log('Click!')
});
Filled/Outlined, label flottant, erreur, helper, icônes
const input = new Input(framework, {
label: 'Email',
placeholder: 'vous@exemple.com',
variant: 'outlined'
});
Toggle avec animation fluide
const toggle = new Switch(framework, {
checked: true,
onChange: (checked) => {
console.log('Switch:', checked);
}
});
Curseur avec drag & animation
const slider = new Slider(framework, {
min: 0, max: 100, value: 50,
onChange: (val) => updateValue(val)
});
Groupes, sélection unique
const radio = new RadioButton(framework, {
group: 'gender',
label: 'Homme',
checked: false
});
Cases à cocher avec animations
const cb = new Checkbox(framework, {
label: 'Accepter',
checked: false
});
Modals avec animations
const dialog = new Dialog(framework, {
title: 'Confirmation',
message: 'Action irréversible',
buttons: ['ANNULER', 'CONFIRMER']
});
Notifications temporaires
const toast = new Toast(framework, {
text: 'Opération réussie !',
duration: 3000
});
toast.show();
Notification avec action
const snack = new Snackbar(framework, {
message: 'Document sauvegardé',
actionText: 'ANNULER',
onAction: () => undo()
});
snack.show();
Photo de profil ou initiales
const avatar = new Avatar(framework, {
initials: 'JD',
size: 48,
status: 'online'
});
Tags et filtres
const chip = new Chip(framework, {
label: 'React',
variant: 'filter',
deletable: true
});
Élément de liste standard
const item = new ListItem(framework, {
title: 'Jean Dupont',
subtitle: 'Cardiologie',
leftIcon: '👤'
});
Item avec swipe actions
const item = new SwipeableListItem(framework, {
title: 'Document',
leftActions: [{
text: 'Archiver',
color: '#388E3C',
onClick: () => archive()
}]
});
Liste virtualisée haute performance
const list = new VirtualList(framework, {
itemHeight: 56,
onItemClick: (index) => console.log(index)
});
Tableau complet avec features
const table = new Table(framework, {
columns: [
{ key: 'name', label: 'Nom' },
{ key: 'age', label: 'Âge' }
],
data: dataArray,
sortable: true
});
Arborescence interactive
const tree = new TreeView(framework, {
data: treeData,
onSelect: (node) => console.log(node)
});
Section extensible animée
const acc = new Accordion(framework, {
title: 'Paramètres avancés',
content: 'Configuration détaillée...',
expanded: false
});
Onglets avec contenu associé
const tabs = new Tabs(framework, {
tabs: [
{ label: 'Accueil', icon: '🏠' },
{ label: 'Profil', icon: '👤' }
],
onChange: (index) => loadPage(index)
});
Barre de navigation inférieure
const nav = new BottomNavigationBar(framework, {
items: [
{ icon: '🏠', label: 'Accueil' },
{ icon: '🔍', label: 'Recherche' }
]
});
Barre d'application supérieure
const appBar = new AppBar(framework, {
title: 'Mon App',
leftIcon: 'menu',
rightIcon: 'search'
});
AppBar expansible/collapsable
const sliver = new SliverAppBar(framework, {
title: 'Profil',
expandedHeight: 200,
collapsedHeight: 56,
parallax: true
});
Menu latéral
const drawer = new Drawer(framework, {
header: { title: 'Menu' },
items: [
{ icon: '🏠', label: 'Accueil' },
{ icon: '⚙️', label: 'Paramètres' }
]
});
drawer.open();
Feuille modale par le bas
const sheet = new BottomSheet(framework, {
height: 400,
dragHandle: true
});
sheet.add(button);
sheet.open();
Fenêtre modale générique
const modal = new Modal(framework, {
title: 'Informations',
width: 300, height: 400
});
modal.add(content);
modal.show();
Menu contextuel
const menu = new ContextMenu(framework, {
options: ['Éditer', 'Copier', 'Supprimer'],
onSelect: (index) => action(index)
});
Floating Action Button
const fab = new FAB(framework, {
icon: '+',
variant: 'large',
onClick: () => addItem()
});
FAB avec menu d'actions
const fab = new SpeedDialFAB(framework, {
actions: [
{ icon: '✉', label: 'Email', action: sendEmail },
{ icon: '📞', label: 'Call', action: makeCall }
]
});
FAB qui se transforme
const fab = new MorphingFAB(framework, {
morphType: 'searchbar',
actions: [...]
});
Spinner circulaire
const spinner = new CircularProgress(framework, {
indeterminate: true,
size: 40
});
Barre de progression linéaire
const bar = new ProgressBar(framework, {
progress: 75,
height: 4
});
Bannière d'information
const banner = new Banner(framework, {
text: 'Mise à jour disponible',
type: 'info',
actions: [{ label: 'Mettre à jour', onClick: update }]
});
Sélecteur de date
const picker = new DatePicker(framework, {
selectedDate: new Date(),
onChange: (date) => console.log(date)
});
Sélecteur d'heure
const timePicker = new TimePicker(framework, {
selectedTime: new Date(),
onChange: (time) => console.log(time)
});
Appareil photo intégré
const camera = new Camera(framework, {
facingMode: 'environment',
onPhoto: (dataUrl) => savePhoto(dataUrl)
});
Lecteur de QR codes
const reader = new QRCodeReader(framework, {
onQRCodeDetected: (data) => console.log(data)
});
Pad de signature
const pad = new SignaturePad(framework, {
strokeColor: '#000000',
onSignatureChange: (points) => console.log(points)
});
Lecteur vidéo
const video = new Video(framework, {
src: 'video.mp4',
onPlay: () => console.log('Playing')
});
Lecteur audio
const player = new AudioPlayer(framework, {
src: '/audio/track.mp3',
onEnded: () => console.log('Finished')
});
Composant d'image
const img = new ImageComponent(framework, {
src: 'photo.jpg',
fit: 'cover',
borderRadius: 8
});
Cartes OpenStreetMap
const map = new OpenStreetMap(framework, {
lat: 48.8566,
lng: 2.3522,
zoom: 13
});
Input numérique
const num = new NumberInput(framework, {
value: 10,
min: 0,
max: 100,
step: 5
});
Champ mot de passe
const pwd = new PasswordInput(framework, {
placeholder: 'Mot de passe'
});
Saisie de tags multiples
const tags = new InputTags(framework, {
tags: ['React', 'Vue'],
onTagAdd: (tag) => console.log('Added:', tag)
});
Input avec autocomplétion
const datalist = new InputDatalist(framework, {
options: ['Paris', 'Lyon', 'Marseille'],
onSelect: (value) => console.log(value)
});
Zone de téléchargement
const upload = new FileUpload(framework, {
accept: '.jpg,.png',
multiple: true,
onFilesSelected: (files) => console.log(files)
});
Menu déroulant
const select = new Select(framework, {
options: ['Option 1', 'Option 2'],
onChange: (value) => console.log(value)
});
Sélection multiple
const multi = new MultiSelectDialog(framework, {
options: ['A', 'B', 'C'],
selectedIndices: [0, 2],
onSelect: (indices, values) => console.log(values)
});
Contrôle segmenté
const seg = new SegmentedControl(framework, {
buttons: [
{ text: 'Jour', onClick: () => setView('day') }
]
});
Incrémenteur/décrémenteur
const stepper = new Stepper(framework, {
value: 1,
min: 0,
max: 10,
onChange: (val) => console.log(val)
});
Graphiques avancés
const chart = new Chart(framework, {
type: 'line',
data: {
labels: ['Jan', 'Feb'],
datasets: [{ data: [10, 20] }]
}
});
Conteneur avec élévation
const card = new Cards(framework, {
padding: 16,
elevation: 4,
borderRadius: 12
}, [text, button]);
Layout horizontal
const row = new Row(framework, {
spacing: 10,
align: 'center'
}, [child1, child2]);
Layout vertical
const col = new Column(framework, {
spacing: 10,
align: 'stretch'
}, [child1, child2]);
Grille responsive
const grid = new Grid(framework, {
columns: 2,
spacing: 10
}, items);
Superposition de composants
const stack = new Stack(framework, {}, [
background,
foreground
]);
Positionnement absolu
const pos = new Positioned(framework, {
child: fab,
bottom: 16,
right: 16
});
Conteneur de liste
const list = new List(framework, {
itemHeight: 56,
onItemClick: (index) => console.log(index)
});
list.addItem({ title: 'Item' });
Séparateur visuel
const divider = new Divider(framework, {
orientation: 'horizontal',
variant: 'inset',
style: 'dashed'
});
Pull-to-refresh autonome
const ptr = new PullToRefresh(framework, {
onRefresh: async () => {
await loadData();
}
});
Placeholder animé
const skeleton = new Skeleton(framework, {
type: 'text',
width: 200,
height: 100
});
Testé en production médicale - 60 FPS stables
// Optimisations activées par défaut const app = new CanvasFramework('app', { useWebGL: true, // Rendu accéléré optimizations: { useDoubleBuffering: true, // Pas de flickering useSpatialPartitioning: true, // Culling viewport useImageDataOptimization: true }, showFps: true // Debug performance });